Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 140 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Get Reward | 20177540 | 6 days ago | IN | 0 ETH | 0.00284249 | ||||
Get Reward | 19784698 | 61 days ago | IN | 0 ETH | 0.00236941 | ||||
Sync | 19756399 | 65 days ago | IN | 0 ETH | 0.00063176 | ||||
Get Reward | 19676184 | 76 days ago | IN | 0 ETH | 0.01280217 | ||||
Get Reward | 19599598 | 87 days ago | IN | 0 ETH | 0.00216522 | ||||
Withdraw Locked | 19599587 | 87 days ago | IN | 0 ETH | 0.00622331 | ||||
Get Reward | 19599399 | 87 days ago | IN | 0 ETH | 0.00371009 | ||||
Withdraw Locked | 19434775 | 110 days ago | IN | 0 ETH | 0.02904669 | ||||
Withdraw Locked | 19198525 | 144 days ago | IN | 0 ETH | 0.01721253 | ||||
Get Reward | 19198521 | 144 days ago | IN | 0 ETH | 0.01165155 | ||||
Withdraw Locked | 19159794 | 149 days ago | IN | 0 ETH | 0.00559815 | ||||
Sync | 19073438 | 161 days ago | IN | 0 ETH | 0.00112592 | ||||
Get Reward | 19049827 | 164 days ago | IN | 0 ETH | 0.00443425 | ||||
Get Reward | 19010574 | 170 days ago | IN | 0 ETH | 0.00346779 | ||||
Withdraw Locked | 19010565 | 170 days ago | IN | 0 ETH | 0.00977903 | ||||
Get Reward | 18858530 | 191 days ago | IN | 0 ETH | 0.00569126 | ||||
Get Reward | 18858491 | 191 days ago | IN | 0 ETH | 0.00549604 | ||||
Sync | 18752010 | 206 days ago | IN | 0 ETH | 0.00428672 | ||||
Get Reward | 18750848 | 206 days ago | IN | 0 ETH | 0.00884039 | ||||
Get Reward | 18617501 | 225 days ago | IN | 0 ETH | 0.00919263 | ||||
Withdraw Locked | 18611489 | 226 days ago | IN | 0 ETH | 0.01940264 | ||||
Withdraw Locked | 18542055 | 236 days ago | IN | 0 ETH | 0.02515234 | ||||
Get Reward | 18484963 | 244 days ago | IN | 0 ETH | 0.00895481 | ||||
Get Reward | 18434263 | 251 days ago | IN | 0 ETH | 0.00509752 | ||||
Withdraw Locked | 18434248 | 251 days ago | IN | 0 ETH | 0.01305903 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FraxUnifiedFarm_ERC20_Convex_frxETH
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-11-03 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.12.0 https://hardhat.org // 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/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/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/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/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/Curve/ICurvefrxETHETHPool.sol interface ICurvefrxETHETHPool { function A() external view returns (uint256); function A_precise() external view returns (uint256); function get_p() external view returns (uint256); function price_oracle() external view returns (uint256); function get_virtual_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 payable 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 set_ma_exp_time(uint256 _ma_exp_time) 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 lp_token() 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 ma_exp_time() external view returns (uint256); function ma_last_time() external view returns (uint256); } // 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; ICurvefrxETHETHPool 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 (USE CHILD FOR LOGIC) -------------------- // 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/Oracle/AggregatorV3Interface.sol interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/Staking/Variants/FraxUnifiedFarm_ERC20_Convex_frxETH.sol contract FraxUnifiedFarm_ERC20_Convex_frxETH is FraxUnifiedFarm_ERC20 { AggregatorV3Interface internal priceFeedETHUSD = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); 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 frxETHETH only stakingToken = IConvexStakingWrapperFrax(_stakingToken); curveToken = I2poolToken(stakingToken.curveToken()); curvePool = ICurvefrxETHETHPool(curveToken.minter()); // address token0 = curvePool.coins(0); // frax_is_token0 = false; // Doesn't matter for frxETH } function getLatestETHPriceE8() public view returns (int) { // Returns in E8 (uint80 roundID, int price, , uint256 updatedAt, uint80 answeredInRound) = priceFeedETHUSD.latestRoundData(); require(price >= 0 && updatedAt!= 0 && answeredInRound >= roundID, "Invalid chainlink price"); return price; } function setETHUSDOracle(address _eth_usd_oracle_address) public onlyByOwnGov { require(_eth_usd_oracle_address != address(0), "Zero address detected"); priceFeedETHUSD = AggregatorV3Interface(_eth_usd_oracle_address); } function fraxPerLPToken() public view override returns (uint256) { // Get the amount of FRAX 'inside' of the lp tokens uint256 frax_per_lp_token; // Convex frxETH/ETH // ============================================ { // Assume frxETH = ETH for pricing purposes // Get the USD value of the frxETH per LP token uint256 frxETH_in_pool = IERC20(0x5E8422345238F34275888049021821E8E08CAa1f).balanceOf(address(curvePool)); uint256 frxETH_usd_val_per_lp_e8 = (frxETH_in_pool * uint256(getLatestETHPriceE8())) / curveToken.totalSupply(); frax_per_lp_token = frxETH_usd_val_per_lp_e8 * (1e10); // We use USD as "Frax" here } 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 ICurvefrxETHETHPool","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":[],"name":"getLatestETHPriceE8","outputs":[{"internalType":"int256","name":"","type":"int256"}],"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":"address","name":"_eth_usd_oracle_address","type":"address"}],"name":"setETHUSDOracle","outputs":[],"stateMutability":"nonpayable","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
60c060405273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b060805273853d955acef822db058eb8505911ed77f175b99e60a052671bc16d674ec8000060068190556301e1338060075562091050600855673782dace9d9000006009819055600a91909155600b55602580546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b84191790553480156200009b57600080fd5b5060405162005bef38038062005bef833981016040819052620000be91620006f3565b86868686868686868686868686856001600160a01b038116620001275760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1506001600255845162000199906010906020880190620004ca565b508151620001af906011906020850190620004ca565b508051620001c5906012906020840190620004ca565b508251620001db90601390602086019062000534565b5060005b855181101562000346578060146000888481518110620002035762000203620007fa565b6020908102919091018101516001600160a01b03168252810191909152604001600090812091909155601580546001810182559082527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47501558451859082908110620002735762000273620007fa565b6020026020010151600f6000888481518110620002945762000294620007fa565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b031916939092169290921790556019805460018181019092557f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969501829055601a8054918201815582527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e0155806200033d8162000826565b915050620001df565b506021805460ff19169055426005819055620003679062093a809062000842565b6004819055505050505050505050505050505080602160056101000a8154816001600160a01b0302191690836001600160a01b03160217905550602160059054906101000a90046001600160a01b03166001600160a01b0316634f39059c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041b91906200085e565b602280546001600160a01b0319166001600160a01b03929092169182179055604080516303aa30b960e11b815290516307546172916004808201926020929091908290030181865afa15801562000476573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200049c91906200085e565b602380546001600160a01b0319166001600160a01b0392909216919091179055506200088395505050505050565b82805482825590600052602060002090810192821562000522579160200282015b828111156200052257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620004eb565b506200053092915062000572565b5090565b82805482825590600052602060002090810192821562000522579160200282015b828111156200052257825182559160200191906001019062000555565b5b8082111562000530576000815560010162000573565b80516001600160a01b0381168114620005a157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620005e757620005e7620005a6565b604052919050565b60006001600160401b038211156200060b576200060b620005a6565b5060051b60200190565b600082601f8301126200062757600080fd5b81516020620006406200063a83620005ef565b620005bc565b82815260059290921b840181019181810190868411156200066057600080fd5b8286015b848110156200068657620006788162000589565b835291830191830162000664565b509695505050505050565b600082601f830112620006a357600080fd5b81516020620006b66200063a83620005ef565b82815260059290921b84018101918181019086841115620006d657600080fd5b8286015b84811015620006865780518352918301918301620006da565b600080600080600080600060e0888a0312156200070f57600080fd5b6200071a8862000589565b60208901519097506001600160401b03808211156200073857600080fd5b620007468b838c0162000615565b975060408a01519150808211156200075d57600080fd5b6200076b8b838c0162000615565b965060608a01519150808211156200078257600080fd5b620007908b838c0162000691565b955060808a0151915080821115620007a757600080fd5b620007b58b838c0162000615565b945060a08a0151915080821115620007cc57600080fd5b50620007db8a828b0162000615565b925050620007ec60c0890162000589565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016200083b576200083b62000810565b5060010190565b8082018082111562000858576200085862000810565b92915050565b6000602082840312156200087157600080fd5b6200087c8262000589565b9392505050565b60805160a051615334620008bb600039600050506000818161108e01528181611143015281816111bd015261234501526153346000f3fe608060405234801561001057600080fd5b506004361061043b5760003560e01c80638980f11f11610235578063d2fbdc0d11610135578063e44b9fa5116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a1e578063facefb6414610a31578063fff6cae914610a4457600080fd5b8063f2a8d34914610a02578063f2caeb1e14610a0b57600080fd5b8063e44b9fa5146109ca578063e7f30582146109dd578063ebe2b12b146109f0578063f288baf6146109f957600080fd5b8063d9f96e8d11610104578063d9f96e8d14610971578063de1a6551146109a7578063e01f62bf146109ba578063e1ba95d2146109c257600080fd5b8063d2fbdc0d14610925578063d42fc9b414610938578063d5e1a9c61461094b578063d7400d561461095e57600080fd5b8063b94c4dcb116101c8578063c8f33c9111610197578063cc2abd641161017c578063cc2abd6414610900578063cdc82e8014610913578063d2010fb41461091c57600080fd5b8063c8f33c91146108c1578063ca6df29d146108ca57600080fd5b8063b94c4dcb1461088a578063bdb123e314610893578063c00007b01461089b578063c3543826146108ae57600080fd5b80639637927f116102045780639637927f1461084e578063a0f234761461085b578063aa1d4fce1461086e578063b85efd061461087757600080fd5b80638980f11f146107da5780638bad86a7146107ed5780638da5cb5b1461081b57806391cf600a1461083b57600080fd5b80634fd2b5361161034057806370641a36116102d35780637910d17b116102a257806379ba50971161028757806379ba50971461079f5780637d6ef08e146107a75780637f472e54146107c757600080fd5b80637910d17b146107515780637970833e1461076457600080fd5b806370641a36146106fa57806372f702f314610702578063741d3c181461072b578063774d4ae71461073e57600080fd5b806364f2c0601161030f57806364f2c060146106a957806369339245146106b15780636c430dbb146106d15780636e27cef9146106f157600080fd5b80634fd2b5361461065b57806353a47bb71461066e578063551897731461068e5780635bfd9258146106a157600080fd5b8063218751b2116103d357806336f89af2116103a2578063387edc8611610387578063387edc86146105f257806341a16f3f146106055780634f39059c1461063b57600080fd5b806336f89af2146105b2578063386a9525146105e857600080fd5b8063218751b214610502578063231b68dc1461054757806328408bab1461056a5780632c0c2a0a1461059f57600080fd5b806317b18c891161040f57806317b18c89146104b45780631c1f78eb146104c75780631e090f01146104cf5780631face856146104ef57600080fd5b80628cc262146104405780630d7bac4f1461046957806312edb24c1461048a5780631627540c1461049f575b600080fd5b61045361044e366004614cf7565b610a4c565b6040516104609190614d12565b60405180910390f35b61047c610477366004614d56565b610bcb565b604051908152602001610460565b610492610bf7565b6040516104609190614d6f565b6104b26104ad366004614cf7565b610c66565b005b61047c6104c2366004614dbd565b610d8b565b610453610e15565b6104e26104dd366004614cf7565b610eb6565b6040516104609190614ddf565b61047c6104fd366004614cf7565b610f6a565b6023546105229073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610460565b61055a610555366004614e4d565b610fb0565b6040519015158152602001610460565b610522610578366004614cf7565b602080526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6105ad366004614cf7565b61101e565b61047c6105c0366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61047c62093a8081565b6104b2610600366004614cf7565b611332565b610522610613366004614cf7565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6022546105229073ffffffffffffffffffffffffffffffffffffffff1681565b61047c610669366004614cf7565b61141c565b6001546105229073ffffffffffffffffffffffffffffffffffffffff1681565b6104b261069c366004614e8e565b61143d565b61047c611561565b601c5461047c565b61047c6106bf366004614cf7565b60146020526000908152604090205481565b61047c6106df366004614cf7565b60186020526000908152604090205481565b61047c60085481565b6104536116d8565b6021546105229065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104b2610739366004614cf7565b611837565b61047c61074c366004614ec5565b61199a565b61045361075f366004614e8e565b611ba6565b610777610772366004614ec5565b611c22565b604080519586526020860194909452928401919091526060830152608082015260a001610460565b6104b2611c70565b61047c6107b5366004614cf7565b601f6020526000908152604090205481565b61047c6107d5366004614cf7565b611dbb565b6104b26107e8366004614ec5565b611dd2565b6108006107fb366004614cf7565b611fbb565b60408051938452602084019290925290820152606001610460565b6000546105229073ffffffffffffffffffffffffffffffffffffffff1681565b6104b2610849366004614cf7565b6121ef565b60215461055a9060ff1681565b61047c610869366004614cf7565b6122e2565b61047c60095481565b6104b2610885366004614dbd565b6123ba565b61047c60075481565b61047c612613565b6104536108a9366004614cf7565b612758565b6105226108bc366004614cf7565b6127e0565b61047c60055481565b61047c6108d8366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526024602052604090205490565b6104b261090e366004614eef565b612842565b61047c60065481565b61047c60035481565b6104b2610933366004614dbd565b612978565b61047c610946366004614cf7565b612cdc565b6104b2610959366004614f3a565b612d18565b6104b261096c366004614cf7565b612f07565b61047c61097f366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b6104b26109b5366004614e4d565b613122565b601b5461047c565b6104b2613209565b61047c6109d8366004614f87565b6132da565b6104b26109eb366004614cf7565b6133c8565b61047c60045481565b61047c600a5481565b61047c600b5481565b61047c610a19366004614d56565b613526565b6104b2610a2c366004614faa565b61363d565b6104b2610a3f366004614ff6565b61380f565b6104b26139cf565b60606000610a586116d8565b60105490915067ffffffffffffffff811115610a7657610a76614fc7565b604051908082528060200260200182016040528015610a9f578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604090205490925015610bc55760005b601054811015610bc35773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351670de0b6b3a76400009190859085908110610b3e57610b3e61509b565b6020026020010151610b5091906150f9565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902054610b80919061510c565b610b8a9190615123565b610b94919061515e565b838281518110610ba657610ba661509b565b602090810291909101015280610bbb81615171565b915050610ad1565b505b50919050565b600654600754600091610bf191610be2828661510c565b610bec9190615123565b6139ff565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610c5c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c31575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610df8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055610e093380858542613a17565b60016002559392505050565b60135460609067ffffffffffffffff811115610e3357610e33614fc7565b604051908082528060200260200182016040528015610e5c578160200160208202803683370190505b50905060005b601354811015610eb25762093a80610e7982613526565b610e83919061510c565b828281518110610e9557610e9561509b565b602090810291909101015280610eaa81615171565b915050610e62565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f5f57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610efb565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054600354670de0b6b3a764000091610fa69161510c565b610bf19190615123565b6000805473ffffffffffffffffffffffffffffffffffffffff90811690841603610fdc57506001610bf1565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f602052604090205481851691160361101557506001610bf1565b50600092915050565b6000808061102b846127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156110fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156110d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f991906151a9565b6111ae565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906151a9565b91506000670de0b6b3a76400007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124a91906151a9565b611254919061510c565b600954600a54611264908661510c565b61126e919061510c565b6112789190615123565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156112a7576112a284611dbb565b6112b0565b6112b08761141c565b90508015611302576000816112cd670de0b6b3a76400008861510c565b6112d79190615123565b9050670de0b6b3a7640000600a54826112f0919061510c565b6112fa9190615123565b925050611307565b600091505b508082116113155780611317565b815b9450600a5485111561132957600a5494505b50505050919050565b600280540361139d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b6002805560215462010000900460ff1615611414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d09565b506001600255565b6000670de0b6b3a7640000600b5461143384612cdc565b610fa6919061510c565b801561144b5761144b6139cf565b73ffffffffffffffffffffffffffffffffffffffff82161561155d57600080600061147585611fbb565b92509250925061148485613e1f565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090208290558281106115085760006114bf84836150f9565b905080601c546114cf919061515e565b601c556114dc818561515e565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e602052604090205550611559565b600061151482856150f9565b905080601c5461152491906150f9565b601c5561153181856150f9565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505b5050505b5050565b6023546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260009081908190735e8422345238f34275888049021821e8e08caa1f906370a0823190602401602060405180830381865afa1580156115ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160e91906151a9565b90506000602260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906151a9565b6116ab612613565b6116b5908461510c565b6116bf9190615123565b90506116d0816402540be40061510c565b949350505050565b6060601b54600014806116eb5750601c54155b15611745576015805480602002602001604051908101604052809291908181526020018280548015610c5c57602002820191906000526020600020905b815481526020019060010190808311611728575050505050905090565b60105467ffffffffffffffff81111561176057611760614fc7565b604051908082528060200260200182016040528015611789578160200160208202803683370190505b50905060005b601554811015610eb257601c546117a582613526565b6005546117b0613f1f565b6117ba91906150f9565b6117c4919061510c565b6117d690670de0b6b3a764000061510c565b6117e09190615123565b601582815481106117f3576117f361509b565b9060005260206000200154611808919061515e565b82828151811061181a5761181a61509b565b60209081029190910101528061182f81615171565b91505061178f565b60005473ffffffffffffffffffffffffffffffffffffffff163314806118705750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6118d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff8116611953576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610d09565b602580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff821660009081526024602052604081208054829190849081106119d4576119d461509b565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260189092528320549193501115611a5257506020810151611a7a565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601860205260409020545b42826060015111611b3a57606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601860205260409020541015611b31576000818360600151611ac891906150f9565b90506000836060015142611adc91906150f9565b90506000611aee610477600285615123565b90506000611afc838261510c565b611b06858461510c565b611b10919061515e565b9050611b1c838561515e565b611b269082615123565b965050505050611b8a565b60009250611b8a565b600080828460600151611b4d91906150f9565b90506000428560600151611b6191906150f9565b90506002611b6f828461515e565b611b799190615123565b92505050611b8681610bcb565b9350505b8160800151831115611b9e57816080015192505b505092915050565b60606002805403611c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055610e09338484613f32565b60246020528160005260406000208181548110611c3e57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610d09565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b5461143384610f6a565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611dff5750611dff3382610fb0565b611e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b6000805b601054811015611edf578473ffffffffffffffffffffffffffffffffffffffff1660108281548110611e9d57611e9d61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611ecd5760019150611edf565b80611ed781615171565b915050611e69565b50808015611f13575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611f3e575080158015611f3e575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611f5457611f4e8433856141fe565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610d09565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080611fec8461101e565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090158015612046575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b80612076575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b156120825750816120c2565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020546002906120b5908561515e565b6120bf9190615123565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602460205260409020548110156121e65773ffffffffffffffffffffffffffffffffffffffff8616600090815260246020526040812080548390811061212d5761212d61509b565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000612186888461199a565b60408301519091506000670de0b6b3a76400006121a3878561515e565b6121ad908461510c565b6121b79190615123565b6121c1908361515e565b90506121cd818861515e565b96505050505080806121de90615171565b9150506120c9565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122285750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61228e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b546122f4919061510c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152670de0b6b3a76400009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b091906151a9565b611433919061510c565b6002805403612425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055336001612436828261143d565b6000806124433387614367565b915091506000858360400151612459919061515e565b90506021546124899065010000000000900473ffffffffffffffffffffffffffffffffffffffff1633308961452c565b6040805160a0810182528881526020858101518183015281830184905260608087015190830152608080870151908301523360009081526024909152919091208054849081106124db576124db61509b565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601b6000828254612530919061515e565b9091555050336000908152601d60205260408120805488929061255490849061515e565b9091555060009050612565336127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156125be5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548992906125b890849061515e565b90915550505b506125ca33600061143d565b604080518881526020810188905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a2505060016002555050505050565b6000806000806000602560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ac91906151dc565b945094505093509350600083121580156126c557508115155b80156126e957508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b61274f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610d09565b50909392505050565b606060028054036127c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b600280556127d533836001613f32565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612812575090565b5073ffffffffffffffffffffffffffffffffffffffff90811660009081526020805260409020541690565b919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061287b5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6128e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b6021805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff931515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff951515630100000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff909316929092179390931791909116179055565b60028054036129e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b600280553360016129f4828261143d565b600080612a013387614367565b91509150428511612a6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610d09565b600042836060015111612a82576000612a92565b428360600151612a9291906150f9565b90506000612aa042886150f9565b9050818111612b0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610d09565b600854811015612b77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d09565b600754811115612be3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d09565b6040518060a0016040528089815260200142815260200185604001518152602001888152602001612c1383610bcb565b9052336000908152602460205260409020805485908110612c3657612c3661509b565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612c8433600061143d565b6040805189815260208101839052428183015260608101899052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a250506001600255505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054600354670de0b6b3a764000091610fa69161510c565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612d455750612d453382610fb0565b612dab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260146020526040902054601380548692908110612de657612de661509b565b9060005260206000200181905550826011601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612e4757612e4761509b565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260149091526040902054601280548492908110612eb857612eb861509b565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612f96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16613030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610d09565b33600090815260208052604090205473ffffffffffffffffffffffffffffffffffffffff1680156130a557336000908152601d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff85168452601f909252822080549192909161309f9084906150f9565b90915550505b3360009081526020808052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601d835281842054908452601f909252822080549192909161311990849061515e565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061314f575061314f3382610fb0565b6131b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314806132425750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6132a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b602180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403613347576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055602154610100900460ff16156133bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610d09565b610e093383856146ca565b336000908152600d602052604090205460ff16613441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d09565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790559180529091205416036135235773ffffffffffffffffffffffffffffffffffffffff811660009081526020808052604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601d825280832054338452601f909252822080549192909161351d9084906150f9565b90915550505b50565b6000806011838154811061353c5761353c61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561361757670de0b6b3a7640000601984815481106135825761358261509b565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135fc91906151a9565b613606919061510c565b6136109190615123565b9150610bc5565b6013838154811061362a5761362a61509b565b9060005260206000200154915050919050565b60005b60115481101561155d5760006011828154811061365f5761365f61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156137fc5782806136b15750601a82815481106136a3576136a361509b565b906000526020600020015442115b156137fc576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374c91906151a9565b6019838154811061375f5761375f61509b565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dc91906151a9565b601a83815481106137ef576137ef61509b565b6000918252602090912001555b508061380781615171565b915050613640565b60005473ffffffffffffffffffffffffffffffffffffffff163314806138485750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6138ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b8051670de0b6b3a76400001115613921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610d09565b608081015160011180159061393b575060a0810151600111155b6139a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610d09565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b6139d9600061363d565b6139e1611561565b60035560045442106139f7576139f561492d565b565b6139f5614c60565b6000818310613a0e5781613a10565b825b9392505050565b6000856001613a26828261143d565b6021546301000000900460ff1615613a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d09565b600854851015613b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d09565b600754851115613b72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d09565b602154613ba09065010000000000900473ffffffffffffffffffffffffffffffffffffffff1688308961452c565b6000613bab86610bcb565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526024835283902060a0850184528185529184018a90529183018b90529092509060608101613c9e8a8a61515e565b815260209081018590528254600181810185556000948552828520845160059093020191825591830151918101919091556040820151600282015560608201516003820155608090910151600490910155601b80548a9290613d0190849061515e565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812080548a9290613d3b90849061515e565b9091555060009050613d4c8b6127e0565b905073ffffffffffffffffffffffffffffffffffffffff811615613da55773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548b9290613d9f90849061515e565b90915550505b50613db18a600061143d565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff811615613523576000613e4682610a4c565b905060005b8151811015613eb457818181518110613e6657613e6661509b565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580613eac81615171565b915050613e4b565b5060005b8151811015611fb65760158181548110613ed457613ed461509b565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580613f1781615171565b915050613eb8565b6000613f2d426004546139ff565b905090565b6060836001613f41828261143d565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902042905560215462010000900460ff1615613fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d09565b60105467ffffffffffffffff811115613ff757613ff7614fc7565b604051908082528060200260200182016040528015614020578160200160208202803683370190505b50925060005b6010548110156141f45773ffffffffffffffffffffffffffffffffffffffff8716600090815260176020908152604080832084845290915290205484518590839081106140755761407561509b565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8816600090815260178252604080822084835290925290812081905584518590839081106140c9576140c961509b565b602002602001015111156141e257614138601082815481106140ed576140ed61509b565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061412b5761412b61509b565b60200260200101516141fe565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff8583815181106141825761418261509b565b60200260200101516010848154811061419d5761419d61509b565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b806141ec81615171565b915050614026565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916142959190615250565b6000604051808303816000865af19150503d80600081146142d2576040519150601f19603f3d011682016040523d82523d6000602084013e6142d7565b606091505b5091509150818015614301575080511580614301575080806020019051810190614301919061526c565b611559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610d09565b61439c6040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff85166000908152602460205260409020548110156144ba5773ffffffffffffffffffffffffffffffffffffffff851660009081526024602052604090208054829081106144045761440461509b565b90600052602060002090600502016000015484036144a85773ffffffffffffffffffffffffffffffffffffffff851660009081526024602052604090208054829081106144535761445361509b565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506144ba565b806144b281615171565b9150506143a0565b5081518314614525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610d09565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916145cb9190615250565b6000604051808303816000865af19150503d8060008114614608576040519150601f19603f3d011682016040523d82523d6000602084013e61460d565b606091505b5091509150818015614637575080511580614637575080806020019051810190614637919061526c565b6146c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610d09565b505050505050565b60006146d884846001613f32565b506000806146e68685614367565b91509150816060015142101580614704575060215460ff1615156001145b61476a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610d09565b60408201518015614923576021546147a29065010000000000900473ffffffffffffffffffffffffffffffffffffffff1687836141fe565b80601b60008282546147b491906150f9565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601d6020526040812080548392906147ee9084906150f9565b90915550600090506147ff886127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156148585773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548492906148529084906150f9565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff871660009081526024602052604090208054839081106148905761489061509b565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556148c890889061143d565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b601254811015614a1e5760006012828154811061494f5761494f61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614a0b576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af11580156149e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a089190615289565b50505b5080614a1681615171565b915050614930565b50600062093a8060045442614a3391906150f9565b614a3d9190615123565b905060005b601054811015614c205760108181548110614a5f57614a5f61509b565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614ad6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614afa91906151a9565b614b0583600161515e565b62093a80614b1284613526565b614b1c919061510c565b614b26919061510c565b111560108281548110614b3b57614b3b61509b565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614c0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0991906152ad565b5080614c1881615171565b915050614a42565b5062093a80614c3082600161515e565b614c3a919061510c565b600454614c47919061515e565b600455614c52614c60565b614c5a611561565b60035550565b6000614c6a6116d8565b905060005b601554811015614cc457818181518110614c8b57614c8b61509b565b602002602001015160158281548110614ca657614ca661509b565b60009182526020909120015580614cbc81615171565b915050614c6f565b50614ccd613f1f565b60055550565b803573ffffffffffffffffffffffffffffffffffffffff8116811461283d57600080fd5b600060208284031215614d0957600080fd5b613a1082614cd3565b6020808252825182820181905260009190848201906040850190845b81811015614d4a57835183529284019291840191600101614d2e565b50909695505050505050565b600060208284031215614d6857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d4a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614d8b565b60008060408385031215614dd057600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e405781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614dfc565b5091979650505050505050565b60008060408385031215614e6057600080fd5b614e6983614cd3565b9150614e7760208401614cd3565b90509250929050565b801515811461352357600080fd5b60008060408385031215614ea157600080fd5b614eaa83614cd3565b91506020830135614eba81614e80565b809150509250929050565b60008060408385031215614ed857600080fd5b614ee183614cd3565b946020939093013593505050565b600080600060608486031215614f0457600080fd5b8335614f0f81614e80565b92506020840135614f1f81614e80565b91506040840135614f2f81614e80565b809150509250925092565b60008060008060808587031215614f5057600080fd5b614f5985614cd3565b935060208501359250614f6e60408601614cd3565b9150614f7c60608601614cd3565b905092959194509250565b60008060408385031215614f9a57600080fd5b82359150614e7760208401614cd3565b600060208284031215614fbc57600080fd5b8135613a1081614e80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561500857600080fd5b82601f83011261501757600080fd5b60405160c0810181811067ffffffffffffffff82111715615061577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561507657600080fd5b845b81811015615090578035835260209283019201615078565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610bf157610bf16150ca565b8082028115828204841417610bf157610bf16150ca565b600082615159577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610bf157610bf16150ca565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036151a2576151a26150ca565b5060010190565b6000602082840312156151bb57600080fd5b5051919050565b805169ffffffffffffffffffff8116811461283d57600080fd5b600080600080600060a086880312156151f457600080fd5b6151fd866151c2565b9450602086015193506040860151925060608601519150615220608087016151c2565b90509295509295909350565b60005b8381101561524757818101518382015260200161522f565b50506000910152565b6000825161526281846020870161522c565b9190910192915050565b60006020828403121561527e57600080fd5b8151613a1081614e80565b6000806040838503121561529c57600080fd5b505080516020909101519092909150565b60208152600082518060208401526152cc81604085016020870161522c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122085b8ef294481f9db096da0d0d8a25492296a2803a77cd8dc0943d23759b00f1164736f6c63430008110033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000004659d5ff63a1e1edd6d5dd9cc315e063c95947d000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061043b5760003560e01c80638980f11f11610235578063d2fbdc0d11610135578063e44b9fa5116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a1e578063facefb6414610a31578063fff6cae914610a4457600080fd5b8063f2a8d34914610a02578063f2caeb1e14610a0b57600080fd5b8063e44b9fa5146109ca578063e7f30582146109dd578063ebe2b12b146109f0578063f288baf6146109f957600080fd5b8063d9f96e8d11610104578063d9f96e8d14610971578063de1a6551146109a7578063e01f62bf146109ba578063e1ba95d2146109c257600080fd5b8063d2fbdc0d14610925578063d42fc9b414610938578063d5e1a9c61461094b578063d7400d561461095e57600080fd5b8063b94c4dcb116101c8578063c8f33c9111610197578063cc2abd641161017c578063cc2abd6414610900578063cdc82e8014610913578063d2010fb41461091c57600080fd5b8063c8f33c91146108c1578063ca6df29d146108ca57600080fd5b8063b94c4dcb1461088a578063bdb123e314610893578063c00007b01461089b578063c3543826146108ae57600080fd5b80639637927f116102045780639637927f1461084e578063a0f234761461085b578063aa1d4fce1461086e578063b85efd061461087757600080fd5b80638980f11f146107da5780638bad86a7146107ed5780638da5cb5b1461081b57806391cf600a1461083b57600080fd5b80634fd2b5361161034057806370641a36116102d35780637910d17b116102a257806379ba50971161028757806379ba50971461079f5780637d6ef08e146107a75780637f472e54146107c757600080fd5b80637910d17b146107515780637970833e1461076457600080fd5b806370641a36146106fa57806372f702f314610702578063741d3c181461072b578063774d4ae71461073e57600080fd5b806364f2c0601161030f57806364f2c060146106a957806369339245146106b15780636c430dbb146106d15780636e27cef9146106f157600080fd5b80634fd2b5361461065b57806353a47bb71461066e578063551897731461068e5780635bfd9258146106a157600080fd5b8063218751b2116103d357806336f89af2116103a2578063387edc8611610387578063387edc86146105f257806341a16f3f146106055780634f39059c1461063b57600080fd5b806336f89af2146105b2578063386a9525146105e857600080fd5b8063218751b214610502578063231b68dc1461054757806328408bab1461056a5780632c0c2a0a1461059f57600080fd5b806317b18c891161040f57806317b18c89146104b45780631c1f78eb146104c75780631e090f01146104cf5780631face856146104ef57600080fd5b80628cc262146104405780630d7bac4f1461046957806312edb24c1461048a5780631627540c1461049f575b600080fd5b61045361044e366004614cf7565b610a4c565b6040516104609190614d12565b60405180910390f35b61047c610477366004614d56565b610bcb565b604051908152602001610460565b610492610bf7565b6040516104609190614d6f565b6104b26104ad366004614cf7565b610c66565b005b61047c6104c2366004614dbd565b610d8b565b610453610e15565b6104e26104dd366004614cf7565b610eb6565b6040516104609190614ddf565b61047c6104fd366004614cf7565b610f6a565b6023546105229073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610460565b61055a610555366004614e4d565b610fb0565b6040519015158152602001610460565b610522610578366004614cf7565b602080526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6105ad366004614cf7565b61101e565b61047c6105c0366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61047c62093a8081565b6104b2610600366004614cf7565b611332565b610522610613366004614cf7565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6022546105229073ffffffffffffffffffffffffffffffffffffffff1681565b61047c610669366004614cf7565b61141c565b6001546105229073ffffffffffffffffffffffffffffffffffffffff1681565b6104b261069c366004614e8e565b61143d565b61047c611561565b601c5461047c565b61047c6106bf366004614cf7565b60146020526000908152604090205481565b61047c6106df366004614cf7565b60186020526000908152604090205481565b61047c60085481565b6104536116d8565b6021546105229065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104b2610739366004614cf7565b611837565b61047c61074c366004614ec5565b61199a565b61045361075f366004614e8e565b611ba6565b610777610772366004614ec5565b611c22565b604080519586526020860194909452928401919091526060830152608082015260a001610460565b6104b2611c70565b61047c6107b5366004614cf7565b601f6020526000908152604090205481565b61047c6107d5366004614cf7565b611dbb565b6104b26107e8366004614ec5565b611dd2565b6108006107fb366004614cf7565b611fbb565b60408051938452602084019290925290820152606001610460565b6000546105229073ffffffffffffffffffffffffffffffffffffffff1681565b6104b2610849366004614cf7565b6121ef565b60215461055a9060ff1681565b61047c610869366004614cf7565b6122e2565b61047c60095481565b6104b2610885366004614dbd565b6123ba565b61047c60075481565b61047c612613565b6104536108a9366004614cf7565b612758565b6105226108bc366004614cf7565b6127e0565b61047c60055481565b61047c6108d8366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526024602052604090205490565b6104b261090e366004614eef565b612842565b61047c60065481565b61047c60035481565b6104b2610933366004614dbd565b612978565b61047c610946366004614cf7565b612cdc565b6104b2610959366004614f3a565b612d18565b6104b261096c366004614cf7565b612f07565b61047c61097f366004614cf7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b6104b26109b5366004614e4d565b613122565b601b5461047c565b6104b2613209565b61047c6109d8366004614f87565b6132da565b6104b26109eb366004614cf7565b6133c8565b61047c60045481565b61047c600a5481565b61047c600b5481565b61047c610a19366004614d56565b613526565b6104b2610a2c366004614faa565b61363d565b6104b2610a3f366004614ff6565b61380f565b6104b26139cf565b60606000610a586116d8565b60105490915067ffffffffffffffff811115610a7657610a76614fc7565b604051908082528060200260200182016040528015610a9f578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604090205490925015610bc55760005b601054811015610bc35773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351670de0b6b3a76400009190859085908110610b3e57610b3e61509b565b6020026020010151610b5091906150f9565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902054610b80919061510c565b610b8a9190615123565b610b94919061515e565b838281518110610ba657610ba661509b565b602090810291909101015280610bbb81615171565b915050610ad1565b505b50919050565b600654600754600091610bf191610be2828661510c565b610bec9190615123565b6139ff565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610c5c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c31575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610df8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055610e093380858542613a17565b60016002559392505050565b60135460609067ffffffffffffffff811115610e3357610e33614fc7565b604051908082528060200260200182016040528015610e5c578160200160208202803683370190505b50905060005b601354811015610eb25762093a80610e7982613526565b610e83919061510c565b828281518110610e9557610e9561509b565b602090810291909101015280610eaa81615171565b915050610e62565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f5f57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610efb565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054600354670de0b6b3a764000091610fa69161510c565b610bf19190615123565b6000805473ffffffffffffffffffffffffffffffffffffffff90811690841603610fdc57506001610bf1565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f602052604090205481851691160361101557506001610bf1565b50600092915050565b6000808061102b846127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156110fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa1580156110d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f991906151a9565b6111ae565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906151a9565b91506000670de0b6b3a76400007f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124a91906151a9565b611254919061510c565b600954600a54611264908661510c565b61126e919061510c565b6112789190615123565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156112a7576112a284611dbb565b6112b0565b6112b08761141c565b90508015611302576000816112cd670de0b6b3a76400008861510c565b6112d79190615123565b9050670de0b6b3a7640000600a54826112f0919061510c565b6112fa9190615123565b925050611307565b600091505b508082116113155780611317565b815b9450600a5485111561132957600a5494505b50505050919050565b600280540361139d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b6002805560215462010000900460ff1615611414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d09565b506001600255565b6000670de0b6b3a7640000600b5461143384612cdc565b610fa6919061510c565b801561144b5761144b6139cf565b73ffffffffffffffffffffffffffffffffffffffff82161561155d57600080600061147585611fbb565b92509250925061148485613e1f565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090208290558281106115085760006114bf84836150f9565b905080601c546114cf919061515e565b601c556114dc818561515e565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e602052604090205550611559565b600061151482856150f9565b905080601c5461152491906150f9565b601c5561153181856150f9565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505b5050505b5050565b6023546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260009081908190735e8422345238f34275888049021821e8e08caa1f906370a0823190602401602060405180830381865afa1580156115ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160e91906151a9565b90506000602260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906151a9565b6116ab612613565b6116b5908461510c565b6116bf9190615123565b90506116d0816402540be40061510c565b949350505050565b6060601b54600014806116eb5750601c54155b15611745576015805480602002602001604051908101604052809291908181526020018280548015610c5c57602002820191906000526020600020905b815481526020019060010190808311611728575050505050905090565b60105467ffffffffffffffff81111561176057611760614fc7565b604051908082528060200260200182016040528015611789578160200160208202803683370190505b50905060005b601554811015610eb257601c546117a582613526565b6005546117b0613f1f565b6117ba91906150f9565b6117c4919061510c565b6117d690670de0b6b3a764000061510c565b6117e09190615123565b601582815481106117f3576117f361509b565b9060005260206000200154611808919061515e565b82828151811061181a5761181a61509b565b60209081029190910101528061182f81615171565b91505061178f565b60005473ffffffffffffffffffffffffffffffffffffffff163314806118705750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6118d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff8116611953576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610d09565b602580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff821660009081526024602052604081208054829190849081106119d4576119d461509b565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260189092528320549193501115611a5257506020810151611a7a565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601860205260409020545b42826060015111611b3a57606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601860205260409020541015611b31576000818360600151611ac891906150f9565b90506000836060015142611adc91906150f9565b90506000611aee610477600285615123565b90506000611afc838261510c565b611b06858461510c565b611b10919061515e565b9050611b1c838561515e565b611b269082615123565b965050505050611b8a565b60009250611b8a565b600080828460600151611b4d91906150f9565b90506000428560600151611b6191906150f9565b90506002611b6f828461515e565b611b799190615123565b92505050611b8681610bcb565b9350505b8160800151831115611b9e57816080015192505b505092915050565b60606002805403611c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055610e09338484613f32565b60246020528160005260406000208181548110611c3e57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610d09565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b5461143384610f6a565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611dff5750611dff3382610fb0565b611e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b6000805b601054811015611edf578473ffffffffffffffffffffffffffffffffffffffff1660108281548110611e9d57611e9d61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611ecd5760019150611edf565b80611ed781615171565b915050611e69565b50808015611f13575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611f3e575080158015611f3e575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611f5457611f4e8433856141fe565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610d09565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080611fec8461101e565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090158015612046575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b80612076575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b156120825750816120c2565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020546002906120b5908561515e565b6120bf9190615123565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602460205260409020548110156121e65773ffffffffffffffffffffffffffffffffffffffff8616600090815260246020526040812080548390811061212d5761212d61509b565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000612186888461199a565b60408301519091506000670de0b6b3a76400006121a3878561515e565b6121ad908461510c565b6121b79190615123565b6121c1908361515e565b90506121cd818861515e565b96505050505080806121de90615171565b9150506120c9565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122285750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61228e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b546122f4919061510c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152670de0b6b3a76400009182917f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa15801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b091906151a9565b611433919061510c565b6002805403612425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055336001612436828261143d565b6000806124433387614367565b915091506000858360400151612459919061515e565b90506021546124899065010000000000900473ffffffffffffffffffffffffffffffffffffffff1633308961452c565b6040805160a0810182528881526020858101518183015281830184905260608087015190830152608080870151908301523360009081526024909152919091208054849081106124db576124db61509b565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601b6000828254612530919061515e565b9091555050336000908152601d60205260408120805488929061255490849061515e565b9091555060009050612565336127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156125be5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548992906125b890849061515e565b90915550505b506125ca33600061143d565b604080518881526020810188905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a2505060016002555050505050565b6000806000806000602560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ac91906151dc565b945094505093509350600083121580156126c557508115155b80156126e957508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b61274f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610d09565b50909392505050565b606060028054036127c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b600280556127d533836001613f32565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612812575090565b5073ffffffffffffffffffffffffffffffffffffffff90811660009081526020805260409020541690565b919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061287b5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6128e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b6021805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff931515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff951515630100000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff909316929092179390931791909116179055565b60028054036129e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b600280553360016129f4828261143d565b600080612a013387614367565b91509150428511612a6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610d09565b600042836060015111612a82576000612a92565b428360600151612a9291906150f9565b90506000612aa042886150f9565b9050818111612b0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610d09565b600854811015612b77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d09565b600754811115612be3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d09565b6040518060a0016040528089815260200142815260200185604001518152602001888152602001612c1383610bcb565b9052336000908152602460205260409020805485908110612c3657612c3661509b565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612c8433600061143d565b6040805189815260208101839052428183015260608101899052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a250506001600255505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054600354670de0b6b3a764000091610fa69161510c565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612d455750612d453382610fb0565b612dab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260146020526040902054601380548692908110612de657612de661509b565b9060005260206000200181905550826011601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612e4757612e4761509b565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260149091526040902054601280548492908110612eb857612eb861509b565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612f96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d09565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16613030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610d09565b33600090815260208052604090205473ffffffffffffffffffffffffffffffffffffffff1680156130a557336000908152601d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff85168452601f909252822080549192909161309f9084906150f9565b90915550505b3360009081526020808052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601d835281842054908452601f909252822080549192909161311990849061515e565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061314f575061314f3382610fb0565b6131b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d09565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314806132425750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6132a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b602180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403613347576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d09565b60028055602154610100900460ff16156133bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610d09565b610e093383856146ca565b336000908152600d602052604090205460ff16613441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d09565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790559180529091205416036135235773ffffffffffffffffffffffffffffffffffffffff811660009081526020808052604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601d825280832054338452601f909252822080549192909161351d9084906150f9565b90915550505b50565b6000806011838154811061353c5761353c61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561361757670de0b6b3a7640000601984815481106135825761358261509b565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135fc91906151a9565b613606919061510c565b6136109190615123565b9150610bc5565b6013838154811061362a5761362a61509b565b9060005260206000200154915050919050565b60005b60115481101561155d5760006011828154811061365f5761365f61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156137fc5782806136b15750601a82815481106136a3576136a361509b565b906000526020600020015442115b156137fc576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374c91906151a9565b6019838154811061375f5761375f61509b565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dc91906151a9565b601a83815481106137ef576137ef61509b565b6000918252602090912001555b508061380781615171565b915050613640565b60005473ffffffffffffffffffffffffffffffffffffffff163314806138485750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6138ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d09565b8051670de0b6b3a76400001115613921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610d09565b608081015160011180159061393b575060a0810151600111155b6139a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610d09565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b6139d9600061363d565b6139e1611561565b60035560045442106139f7576139f561492d565b565b6139f5614c60565b6000818310613a0e5781613a10565b825b9392505050565b6000856001613a26828261143d565b6021546301000000900460ff1615613a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d09565b600854851015613b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d09565b600754851115613b72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d09565b602154613ba09065010000000000900473ffffffffffffffffffffffffffffffffffffffff1688308961452c565b6000613bab86610bcb565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526024835283902060a0850184528185529184018a90529183018b90529092509060608101613c9e8a8a61515e565b815260209081018590528254600181810185556000948552828520845160059093020191825591830151918101919091556040820151600282015560608201516003820155608090910151600490910155601b80548a9290613d0190849061515e565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812080548a9290613d3b90849061515e565b9091555060009050613d4c8b6127e0565b905073ffffffffffffffffffffffffffffffffffffffff811615613da55773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548b9290613d9f90849061515e565b90915550505b50613db18a600061143d565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff811615613523576000613e4682610a4c565b905060005b8151811015613eb457818181518110613e6657613e6661509b565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580613eac81615171565b915050613e4b565b5060005b8151811015611fb65760158181548110613ed457613ed461509b565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580613f1781615171565b915050613eb8565b6000613f2d426004546139ff565b905090565b6060836001613f41828261143d565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902042905560215462010000900460ff1615613fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d09565b60105467ffffffffffffffff811115613ff757613ff7614fc7565b604051908082528060200260200182016040528015614020578160200160208202803683370190505b50925060005b6010548110156141f45773ffffffffffffffffffffffffffffffffffffffff8716600090815260176020908152604080832084845290915290205484518590839081106140755761407561509b565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8816600090815260178252604080822084835290925290812081905584518590839081106140c9576140c961509b565b602002602001015111156141e257614138601082815481106140ed576140ed61509b565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061412b5761412b61509b565b60200260200101516141fe565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff8583815181106141825761418261509b565b60200260200101516010848154811061419d5761419d61509b565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b806141ec81615171565b915050614026565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916142959190615250565b6000604051808303816000865af19150503d80600081146142d2576040519150601f19603f3d011682016040523d82523d6000602084013e6142d7565b606091505b5091509150818015614301575080511580614301575080806020019051810190614301919061526c565b611559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610d09565b61439c6040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff85166000908152602460205260409020548110156144ba5773ffffffffffffffffffffffffffffffffffffffff851660009081526024602052604090208054829081106144045761440461509b565b90600052602060002090600502016000015484036144a85773ffffffffffffffffffffffffffffffffffffffff851660009081526024602052604090208054829081106144535761445361509b565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506144ba565b806144b281615171565b9150506143a0565b5081518314614525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610d09565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916145cb9190615250565b6000604051808303816000865af19150503d8060008114614608576040519150601f19603f3d011682016040523d82523d6000602084013e61460d565b606091505b5091509150818015614637575080511580614637575080806020019051810190614637919061526c565b6146c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610d09565b505050505050565b60006146d884846001613f32565b506000806146e68685614367565b91509150816060015142101580614704575060215460ff1615156001145b61476a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610d09565b60408201518015614923576021546147a29065010000000000900473ffffffffffffffffffffffffffffffffffffffff1687836141fe565b80601b60008282546147b491906150f9565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601d6020526040812080548392906147ee9084906150f9565b90915550600090506147ff886127e0565b905073ffffffffffffffffffffffffffffffffffffffff8116156148585773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548492906148529084906150f9565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff871660009081526024602052604090208054839081106148905761489061509b565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556148c890889061143d565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b601254811015614a1e5760006012828154811061494f5761494f61509b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614a0b576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af11580156149e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a089190615289565b50505b5080614a1681615171565b915050614930565b50600062093a8060045442614a3391906150f9565b614a3d9190615123565b905060005b601054811015614c205760108181548110614a5f57614a5f61509b565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614ad6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614afa91906151a9565b614b0583600161515e565b62093a80614b1284613526565b614b1c919061510c565b614b26919061510c565b111560108281548110614b3b57614b3b61509b565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614c0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0991906152ad565b5080614c1881615171565b915050614a42565b5062093a80614c3082600161515e565b614c3a919061510c565b600454614c47919061515e565b600455614c52614c60565b614c5a611561565b60035550565b6000614c6a6116d8565b905060005b601554811015614cc457818181518110614c8b57614c8b61509b565b602002602001015160158281548110614ca657614ca661509b565b60009182526020909120015580614cbc81615171565b915050614c6f565b50614ccd613f1f565b60055550565b803573ffffffffffffffffffffffffffffffffffffffff8116811461283d57600080fd5b600060208284031215614d0957600080fd5b613a1082614cd3565b6020808252825182820181905260009190848201906040850190845b81811015614d4a57835183529284019291840191600101614d2e565b50909695505050505050565b600060208284031215614d6857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d4a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614d8b565b60008060408385031215614dd057600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e405781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614dfc565b5091979650505050505050565b60008060408385031215614e6057600080fd5b614e6983614cd3565b9150614e7760208401614cd3565b90509250929050565b801515811461352357600080fd5b60008060408385031215614ea157600080fd5b614eaa83614cd3565b91506020830135614eba81614e80565b809150509250929050565b60008060408385031215614ed857600080fd5b614ee183614cd3565b946020939093013593505050565b600080600060608486031215614f0457600080fd5b8335614f0f81614e80565b92506020840135614f1f81614e80565b91506040840135614f2f81614e80565b809150509250925092565b60008060008060808587031215614f5057600080fd5b614f5985614cd3565b935060208501359250614f6e60408601614cd3565b9150614f7c60608601614cd3565b905092959194509250565b60008060408385031215614f9a57600080fd5b82359150614e7760208401614cd3565b600060208284031215614fbc57600080fd5b8135613a1081614e80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561500857600080fd5b82601f83011261501757600080fd5b60405160c0810181811067ffffffffffffffff82111715615061577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561507657600080fd5b845b81811015615090578035835260209283019201615078565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610bf157610bf16150ca565b8082028115828204841417610bf157610bf16150ca565b600082615159577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610bf157610bf16150ca565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036151a2576151a26150ca565b5060010190565b6000602082840312156151bb57600080fd5b5051919050565b805169ffffffffffffffffffff8116811461283d57600080fd5b600080600080600060a086880312156151f457600080fd5b6151fd866151c2565b9450602086015193506040860151925060608601519150615220608087016151c2565b90509295509295909350565b60005b8381101561524757818101518382015260200161522f565b50506000910152565b6000825161526281846020870161522c565b9190910192915050565b60006020828403121561527e57600080fd5b8151613a1081614e80565b6000806040838503121561529c57600080fd5b505080516020909101519092909150565b60208152600082518060208401526152cc81604085016020870161522c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122085b8ef294481f9db096da0d0d8a25492296a2803a77cd8dc0943d23759b00f1164736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000004659d5ff63a1e1edd6d5dd9cc315e063c95947d000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
-----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): 0x4659d5fF63A1E1EDD6D5DD9CC315e063c95947d0
-----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] : 0000000000000000000000004659d5ff63a1e1edd6d5dd9cc315e063c95947d0
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
92480:2384:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35332:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37542:477;;;;;;:::i;:::-;;:::i;:::-;;;1374:25:1;;;1362:2;1347:18;37542:477:0;1228:177:1;33611:109:0;;;:::i;:::-;;;;;;;:::i;22957:141::-;;;;;;:::i;:::-;;:::i;:::-;;86536:190;;;;;;:::i;:::-;;:::i;35925:339::-;;;:::i;81791:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;38238:179::-;;;;;;:::i;:::-;;:::i;70533:36::-;;;;;;;;;;;;3751:42:1;3739:55;;;3721:74;;3709:2;3694:18;70533:36:0;3547:254:1;33275:298:0;;;;;;:::i;:::-;;:::i;:::-;;;4236:14:1;;4229:22;4211:41;;4199:2;4184:18;33275:298:0;4071:187:1;30651:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;39786:1752;;;;;;:::i;:::-;;:::i;36978:127::-;;;;;;:::i;:::-;37071:26;;37044:7;37071:26;;;:17;:26;;;;;;;36978:127;29591:48;;29633:6;29591:48;;45653:238;;;;;;:::i;:::-;;:::i;29219:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;70464:29;;;;;;;;;38938:181;;;;;;:::i;:::-;;:::i;22725:29::-;;;;;;;;;43487:1522;;;;;;:::i;:::-;;:::i;94082:779::-;;;:::i;36692:111::-;36773:22;;36692:111;;29472:55;;;;;;:::i;:::-;;;;;;;;;;;;;;29983:54;;;;;;:::i;:::-;;;;;;;;;;;;;;28493:37;;;;;;34435:681;;;:::i;70412:45::-;;;;;;;;;;;;93829:245;;;;;;:::i;:::-;;:::i;76982:2692::-;;;;;;:::i;:::-;;:::i;46360:206::-;;;;;;:::i;:::-;;:::i;71101:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;5971:25:1;;;6027:2;6012:18;;6005:34;;;;6055:18;;;6048:34;;;;6113:2;6098:18;;6091:34;6156:3;6141:19;;6134:35;5958:3;5943:19;71101:53:0;5712:463:1;23106:271:0;;;:::i;30442:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;39127:199;;;;;;:::i;:::-;;:::i;53358:1013::-;;;;;;:::i;:::-;;:::i;79735:1961::-;;;;;;:::i;:::-;;:::i;:::-;;;;6382:25:1;;;6438:2;6423:18;;6416:34;;;;6466:18;;;6459:34;6370:2;6355:18;79735:1961:0;6180:319:1;22698:20:0;;;;;;;;;53068:161;;;;;;:::i;:::-;;:::i;30842:26::-;;;;;;;;;38520:224;;;;;;:::i;:::-;;:::i;28587:55::-;;;;;;83665:1325;;;;;;:::i;:::-;;:::i;28340:61::-;;;;;;93474:347;;;:::i;46180:172::-;;;;;;:::i;:::-;;:::i;39334:444::-;;;;;;:::i;:::-;;:::i;28186:29::-;;;;;;82000:133;;;;;;:::i;:::-;82097:21;;82070:7;82097:21;;;:12;:21;;;;;:28;;82000:133;52518:311;;;;;;:::i;:::-;;:::i;28266:50::-;;;;;;27989:30;;;;;;85044:1357;;;;;;:::i;:::-;;:::i;38064:166::-;;;;;;:::i;:::-;;:::i;55414:483::-;;;;;;:::i;:::-;;:::i;42521:800::-;;;;;;:::i;:::-;;:::i;36526:128::-;;;;;;:::i;:::-;36620:26;;36593:7;36620:26;;;:17;:26;;;;;;;36526:128;55972:207;;;;;;:::i;:::-;;:::i;36362:113::-;36444:23;;36362:113;;52922:97;;;:::i;88799:259::-;;;;;;:::i;:::-;;:::i;41796:610::-;;;;;;:::i;:::-;;:::i;28152:27::-;;;;;;28725:51;;;;;;28801:59;;;;;;33913:452;;;;;;:::i;:::-;;:::i;51208:761::-;;;;;;:::i;:::-;;:::i;54379:958::-;;;;;;:::i;:::-;;:::i;51977:363::-;;;:::i;35332:529::-;35386:27;35426;35456:17;:15;:17::i;:::-;35511:12;:19;35426:47;;-1:-1:-1;35497:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35497:34:0;-1:-1:-1;35548:26:0;;;35577:1;35548:26;;;:17;:26;;;;;;35484:47;;-1:-1:-1;35548:30:0;35544:310;;35599:9;35594:249;35618:12;:19;35614:23;;35594:249;;;35808:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;35727:32;;;:23;:32;;;;;:35;;;;;;;;;35711:13;;35767:4;;35727:35;35711:10;;35825:1;;35711:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;35681:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;35680:91;;;;:::i;:::-;35679:148;;;;:::i;:::-;35663:10;35674:1;35663:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;35639:3;;;;:::i;:::-;;;;35594:249;;;;35544:310;35415:446;35332:529;;;:::o;37542:477::-;37906:19;;37971:28;;37601:7;;37883:127;;37941:26;37906:19;37941:4;:26;:::i;:::-;37940:59;;;;:::i;:::-;37883:8;:127::i;:::-;37876:134;37542:477;-1:-1:-1;;37542:477:0:o;33611:109::-;33664:16;33700:12;33693:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33611:109;:::o;22957:141::-;23437:5;;;;23423:10;:19;23415:79;;;;;;;10970:2:1;23415:79:0;;;10952:21:1;11009:2;10989:18;;;10982:30;11048:34;11028:18;;;11021:62;11119:17;11099:18;;;11092:45;11154:19;;23415:79:0;;;;;;;;;23029:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;23068:22:::1;::::0;3721:74:1;;;23068:22:0::1;::::0;3709:2:1;3694:18;23068:22:0::1;;;;;;;22957:141:::0;:::o;86536:190::-;86621:7;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;86648:70:::1;86661:10;::::0;86685:9;86696:4;86702:15:::1;86648:12;:70::i;:::-;21588:1:::0;22550:7;:22;86641:77;86536:190;-1:-1:-1;;;86536:190:0:o;35925:339::-;36075:17;:24;35980:41;;36061:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36061:39:0;;36034:66;;36118:9;36113:144;36137:17;:24;36133:28;;36113:144;;;29633:6;36213:14;36225:1;36213:11;:14::i;:::-;:32;;;;:::i;:::-;36183:24;36208:1;36183:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;36163:3;;;;:::i;:::-;;;;36113:144;;;;35925:339;:::o;81791:133::-;81895:21;;;;;;;:12;:21;;;;;;;;81888:28;;;;;;;;;;;;;;;;;81855:20;;81888:28;;81895:21;;81888:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81791:133;;;:::o;38238:179::-;38353:32;;;38307:7;38353:32;;;:17;:32;;;;;;38335:15;;28117:4;;38335:50;;;:::i;:::-;38334:75;;;;:::i;33275:298::-;33371:4;33406:5;;;;;;33391:20;;;;33387:136;;-1:-1:-1;33420:4:0;33413:11;;33387:136;33462:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;33458:65;;-1:-1:-1;33519:4:0;33512:11;;33458:65;-1:-1:-1;33559:5:0;33275:298;;;;:::o;39786:1752::-;39849:24;;;40010:20;40022:7;40010:11;:20::i;:::-;39990:40;-1:-1:-1;40061:23:0;;;;40060:81;;40115:26;;;;;:15;3739:55:1;;;40115:26:0;;;3721:74:1;40115:5:0;:15;;;;3694:18:1;;40115:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40060:81;;;40088:24;;;;;:15;3739:55:1;;;40088:24:0;;;3721:74:1;40088:5:0;:15;;;;3694:18:1;;40088:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40041:100;;40247:19;28117:4;40371:5;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;40312:24;;40289:20;;40270:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;40269:145;;;;:::i;:::-;40247:167;-1:-1:-1;40523:19:0;;40738:23;;;;40737:94;;40796:35;40821:9;40796:24;:35::i;:::-;40737:94;;;40765:28;40785:7;40765:19;:28::i;:::-;40708:123;-1:-1:-1;40852:30:0;;40848:323;;40903:27;40977:26;40934:39;28117:4;40934:16;:39;:::i;:::-;40933:70;;;;:::i;:::-;40903:100;;28117:4;41077:20;;41055:19;:42;;;;:::i;:::-;41054:67;;;;:::i;:::-;41040:81;;40883:254;40848:323;;;41170:1;41156:15;;40848:323;40553:699;41339:11;41325;:25;:53;;41367:11;41325:53;;;41353:11;41325:53;41305:74;;41469:20;;41450:16;:39;41446:84;;;41510:20;;41491:39;;41446:84;39875:1663;;;;39786:1752;;;:::o;45653:238::-;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;45750:23:::1;::::0;;;::::1;;;:32;45742:70;;;::::0;::::1;::::0;;11935:2:1;45742:70:0::1;::::0;::::1;11917:21:1::0;11974:2;11954:18;;;11947:30;12013:27;11993:18;;;11986:55;12058:18;;45742:70:0::1;11733:349:1::0;45742:70:0::1;-1:-1:-1::0;21588:1:0;22550:7;:22;45653:238::o;38938:181::-;39005:7;28117:4;39059:28;;39033:23;39048:7;39033:14;:23::i;:::-;:54;;;;:::i;43487:1522::-;43674:8;43670:46;;;43698:6;:4;:6::i;:::-;43740:21;;;;43736:1266;;43954:27;44000:28;44047:27;44092:30;44114:7;44092:21;:30::i;:::-;43932:190;;;;;;44184:20;44196:7;44184:11;:20::i;:::-;44280:31;;;;;;;:22;:31;;;;;:54;;;44421:42;;;44417:572;;44484:19;44506:41;44528:19;44506;:41;:::i;:::-;44484:63;;44616:11;44591:22;;:36;;;;:::i;:::-;44566:22;:61;44675:33;44697:11;44675:19;:33;:::i;:::-;44646:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;44417:572:0;;;44749:19;44771:41;44793:19;44771;:41;:::i;:::-;44749:63;;44881:11;44856:22;;:36;;;;:::i;:::-;44831:22;:61;44940:33;44962:11;44940:19;:33;:::i;:::-;44911:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;44417:572:0;43763:1239;;;43736:1266;43487:1522;;:::o;94082:779::-;94571:9;;94502:80;;;;;:60;94571:9;;;94502:80;;;3721:74:1;94138:7:0;;;;;;94509:42;;94502:60;;3694:18:1;;94502:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94477:105;;94597:32;94684:10;;;;;;;;;;;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94658:21;:19;:21::i;:::-;94633:47;;:14;:47;:::i;:::-;94632:76;;;;:::i;:::-;94597:111;-1:-1:-1;94743:33:0;94597:111;94771:4;94743:33;:::i;:::-;94723:53;94082:779;-1:-1:-1;;;;94082:779:0:o;34435:681::-;34483:41;34541:23;;34568:1;34541:28;:59;;;-1:-1:-1;34573:22:0;;:27;34541:59;34537:572;;;34624:21;34617:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34435:681;:::o;34537:572::-;34728:12;:19;34714:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34714:34:0;;34687:61;;34768:9;34763:289;34787:21;:28;34783:32;;34763:289;;;34995:22;;34970:14;34982:1;34970:11;:14::i;:::-;34952;;34923:26;:24;:26::i;:::-;:43;;;;:::i;:::-;34922:62;;;;:::i;:::-;:69;;34987:4;34922:69;:::i;:::-;34921:96;;;;:::i;:::-;34871:21;34893:1;34871:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;34841:24;34866:1;34841:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;34817:3;;;;:::i;:::-;;;;34763:289;;93829:245;31266:5;;;;31252:10;:19;;:79;;-1:-1:-1;31289:42:0;31275:10;:56;31252:79;31244:113;;;;;;;12289:2:1;31244:113:0;;;12271:21:1;12328:2;12308:18;;;12301:30;12367:23;12347:18;;;12340:51;12408:18;;31244:113:0;12087:345:1;31244:113:0;93926:37:::1;::::0;::::1;93918:71;;;::::0;::::1;::::0;;12639:2:1;93918:71:0::1;::::0;::::1;12621:21:1::0;12678:2;12658:18;;;12651:30;12717:23;12697:18;;;12690:51;12758:18;;93918:71:0::1;12437:345:1::0;93918:71:0::1;94002:15;:64:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;93829:245::o;76982:2692::-;77173:21;;;77071:32;77173:21;;;:12;:21;;;;;:32;;77071;;77173:21;77195:9;;77173:32;;;;;;:::i;:::-;;;;;;;;;77142:63;;;;;;;;77173:32;;;;;;;77142:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77388:28;;;;;:19;:28;;;;;;77142:63;;-1:-1:-1;;77384:224:0;;;-1:-1:-1;77481:25:0;;;;77384:224;;;-1:-1:-1;77568:28:0;;;;;;;:19;:28;;;;;;77384:224;77697:15;77667:9;:26;;;:45;77663:1802;;77892:26;;;;77861:28;;;;;;;:19;:28;;;;;;:57;77857:1087;;;77938:26;77996:17;77967:9;:26;;;:46;;;;:::i;:::-;77938:75;;78032:25;78078:9;:26;;;78060:15;:44;;;;:::i;:::-;78032:72;-1:-1:-1;78184:33:0;78220:38;78235:22;78256:1;78235:18;:22;:::i;78220:38::-;78184:74;-1:-1:-1;78475:17:0;78547:21;78551:17;78475;78547:21;:::i;:::-;78496:46;78524:18;78496:25;:46;:::i;:::-;78495:74;;;;:::i;:::-;78475:94;-1:-1:-1;78628:38:0;78649:17;78628:18;:38;:::i;:::-;78615:52;;:9;:52;:::i;:::-;78588:79;;77919:764;;;;77663:1802;;77857:1087;78927:1;78900:28;;77663:1802;;;79089:21;79144:20;79196:17;79167:9;:26;;;:46;;;;:::i;:::-;79144:69;;79232:20;79284:15;79255:9;:26;;;:44;;;;:::i;:::-;79232:67;-1:-1:-1;79366:1:0;79335:27;79232:67;79335:12;:27;:::i;:::-;79334:33;;;;:::i;:::-;79318:49;;79125:258;;79424:29;79439:13;79424:14;:29::i;:::-;79397:56;;79009:456;77663:1802;79587:9;:25;;;79560:24;:52;79556:110;;;79641:9;:25;;;79614:52;;79556:110;77105:2569;;76982:2692;;;;:::o;46360:206::-;46462:16;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;46498:60:::1;46509:10;46521:19:::0;46542:15;46498:10:::1;:60::i;71101:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;71101:53:0;;-1:-1:-1;71101:53:0;;;:::o;23106:271::-;23175:14;;;;23161:10;:28;23153:94;;;;;;;12989:2:1;23153:94:0;;;12971:21:1;13028:2;13008:18;;;13001:30;13067:34;13047:18;;;13040:62;13138:23;13118:18;;;13111:51;13179:19;;23153:94:0;12787:417:1;23153:94:0;23276:5;;;23283:14;23263:35;;;23276:5;;;;13444:34:1;;23283:14:0;;;;13509:2:1;13494:18;;13487:43;23263:35:0;;13356:18:1;23263:35:0;;;;;;;23317:14;;;;23309:22;;;;;;23317:14;;;23309:22;;;;23342:27;;;23106:271::o;39127:199::-;39205:7;28117:4;39266:28;;39233:30;39249:13;39233:15;:30::i;53358:1013::-;31469:5;;53444:12;;31469:5;;31455:10;:19;;:74;;;31478:51;31496:10;31508:20;31478:17;:51::i;:::-;31447:107;;;;;;;13743:2:1;31447:107:0;;;13725:21:1;13782:2;13762:18;;;13755:30;13821:22;13801:18;;;13794:50;13861:18;;31447:107:0;13541:344:1;31447:107:0;53526:18:::1;53568:9:::0;53563:192:::1;53587:12;:19:::0;53583:23;::::1;53563:192;;;53651:12;53632:31;;:12;53645:1;53632:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:31:::0;53628:116:::1;;53700:4;53684:20;;53723:5;;53628:116;53608:3:::0;::::1;::::0;::::1;:::i;:::-;;;;53563:192;;;;53981:13;:59;;;;-1:-1:-1::0;53998:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;54030:10;53998:42;53981:59;53980:123;;;;54064:13;54063:14;:39;;;;-1:-1:-1::0;54096:5:0::1;::::0;::::1;;54082:10;:19;54063:39;53958:406;;;54134:66;54162:12;54176:10;54188:11;54134:27;:66::i;:::-;54215:7;53358:1013:::0;;;:::o;53958:406::-:1;54316:36;::::0;::::1;::::0;;14092:2:1;54316:36:0::1;::::0;::::1;14074:21:1::0;14131:2;14111:18;;;14104:30;14170:28;14150:18;;;14143:56;14216:18;;54316:36:0::1;13890:350:1::0;31565:1:0::1;53358:1013:::0;;;:::o;79735:1961::-;80038:26;;;79836:27;80038:26;;;:17;:26;;;;;;;79836:27;80225:24;80056:7;80225:15;:24::i;:::-;80325:26;;;80262:33;80325:26;;;:17;:26;;;;;;80202:47;;-1:-1:-1;80262:33:0;80325:31;:66;;;;-1:-1:-1;80360:26:0;;;;;;;:17;:26;;;;;;:31;80325:66;80324:143;;;-1:-1:-1;80435:31:0;;;;;;;:22;:31;;;;;;80411:55;;;80324:143;80306:638;;;-1:-1:-1;80708:20:0;80306:638;;;80896:31;;;;;;;:22;:31;;;;;;80931:1;;80873:54;;:20;:54;:::i;:::-;80872:60;;;;:::i;:::-;80844:88;;80306:638;81079:1;81057:23;;81096:9;81091:598;81115:21;;;;;;;:12;:21;;;;;:28;81111:32;;81091:598;;;81196:21;;;81165:28;81196:21;;;:12;:21;;;;;:24;;81218:1;;81196:24;;;;;;:::i;:::-;;;;;;;;;;;81165:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81292:32;81327:34;81350:7;81359:1;81327:22;:34::i;:::-;81443:19;;;;81292:69;;-1:-1:-1;81423:17:0;28117:4;81538:52;81565:25;81292:69;81538:52;:::i;:::-;81525:66;;:9;:66;:::i;:::-;81524:91;;;;:::i;:::-;81511:105;;:9;:105;:::i;:::-;81477:139;-1:-1:-1;81631:46:0;81477:139;81631:46;;:::i;:::-;;;81150:539;;;;81145:3;;;;;:::i;:::-;;;;81091:598;;;;79965:1731;79735:1961;;;;;:::o;53068:161::-;31266:5;;;;31252:10;:19;;:79;;-1:-1:-1;31289:42:0;31275:10;:56;31252:79;31244:113;;;;;;;12289:2:1;31244:113:0;;;12271:21:1;12328:2;12308:18;;;12301:30;12367:23;12347:18;;;12340:51;12408:18;;31244:113:0;12087:345:1;31244:113:0;53189:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;53153:68;;::::1;53189:32;::::0;;::::1;53188:33;53153:68;::::0;;53068:161::o;38520:224::-;38586:7;38720:15;;38689:28;;:46;;;;:::i;:::-;38614:24;;;;;:15;3739:55:1;;;38614:24:0;;;3721:74:1;28117:4:0;;;;38614:5;:15;;;;3694:18:1;;38614:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;83665:1325::-;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;83762:10:::1;83774:4;31660:41;83762:10:::0;83774:4;31660:22:::1;:41::i;:::-;83839:28:::2;83869:21:::0;83894:29:::2;83904:10;83916:6;83894:9;:29::i;:::-;83838:85;;;;83973:15;84013:8;83991:9;:19;;;:30;;;;:::i;:::-;83973:48:::0;-1:-1:-1;84192:12:0::2;::::0;84152:91:::2;::::0;84192:12;;::::2;;;84207:10;84227:4;84234:8:::0;84152:31:::2;:91::i;:::-;84327:186;::::0;;::::2;::::0;::::2;::::0;;;;;::::2;84374:25:::0;;::::2;::::0;84327:186;;::::2;::::0;;;;;;;;84436:26;;::::2;::::0;84327:186;;;;;84477:25;;::::2;::::0;84327:186;;;;84298:10:::2;-1:-1:-1::0;84285:24:0;;;:12:::2;:24:::0;;;;;;;:39;;84310:13;;84285:39;::::2;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84584:8;84557:23;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;84621:10:0::2;84603:29;::::0;;;:17:::2;:29;::::0;;;;:41;;84636:8;;84603:29;:41:::2;::::0;84636:8;;84603:41:::2;:::i;:::-;::::0;;;-1:-1:-1;84670:17:0::2;::::0;-1:-1:-1;84690:23:0::2;84702:10;84690:11;:23::i;:::-;84670:43:::0;-1:-1:-1;84732:23:0::2;::::0;::::2;::::0;84728:69:::2;;84757:28;::::0;::::2;;::::0;;;:17:::2;:28;::::0;;;;:40;;84789:8;;84757:28;:40:::2;::::0;84789:8;;84757:40:::2;:::i;:::-;::::0;;;-1:-1:-1;;84728:69:0::2;84655:154;84877:41;84900:10;84912:5;84877:22;:41::i;:::-;84936:46;::::0;;14764:25:1;;;14820:2;14805:18;;14798:34;;;84953:10:0::2;::::0;84936:46:::2;::::0;14737:18:1;84936:46:0::2;;;;;;;-1:-1:-1::0;;21588:1:0;22550:7;:22;-1:-1:-1;;;;;83665:1325:0:o;93474:347::-;93526:3;93569:14;93585:9;93598:17;93617:22;93643:15;;;;;;;;;;;:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93568:108;;;;;;;;;93704:1;93695:5;:10;;:27;;;;-1:-1:-1;93709:13:0;;;93695:27;:57;;;;;93745:7;93726:26;;:15;:26;;;;93695:57;93687:93;;;;;;;15707:2:1;93687:93:0;;;15689:21:1;15746:2;15726:18;;;15719:30;15785:25;15765:18;;;15758:53;15828:18;;93687:93:0;15505:347:1;93687:93:0;-1:-1:-1;93808:5:0;;93474:347;-1:-1:-1;;;93474:347:0:o;46180:172::-;46259:16;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;46295:49:::1;46306:10;46318:19:::0;46339:4:::1;46295:10;:49::i;:::-;21588:1:::0;22550:7;:22;46288:56;46180:172;-1:-1:-1;;46180:172:0:o;39334:444::-;39413:25;;;39390:7;39413:25;;;:19;:25;;;;;;;;39409:362;;;-1:-1:-1;39616:4:0;39334:444::o;39409:362::-;-1:-1:-1;39728:31:0;;;;;;;;:25;:31;;;;;;;;39334:444::o;39409:362::-;39334:444;;;:::o;52518:311::-;31266:5;;;;31252:10;:19;;:79;;-1:-1:-1;31289:42:0;31275:10;:56;31252:79;31244:113;;;;;;;12289:2:1;31244:113:0;;;12271:21:1;12328:2;12308:18;;;12301:30;12367:23;12347:18;;;12340:51;12408:18;;31244:113:0;12087:345:1;31244:113:0;52681:13:::1;:30:::0;;52771:50;::::1;;::::0;::::1;::::0;52722:38;::::1;;52681:30;52722:38;::::0;52681:30;::::1;;::::0;::::1;52722:38:::0;;;;;;;;;;;;;;;::::1;52771:50:::0;;;::::1;;::::0;;52518:311::o;85044:1357::-;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;85142:10:::1;85154:4;31660:41;85142:10:::0;85154:4;31660:22:::1;:41::i;:::-;85219:28:::2;85249:21:::0;85274:29:::2;85284:10;85296:6;85274:9;:29::i;:::-;85218:85;;;;85358:15;85342:13;:31;85334:65;;;::::0;::::2;::::0;;16059:2:1;85334:65:0::2;::::0;::::2;16041:21:1::0;16098:2;16078:18;;;16071:30;16137:23;16117:18;;;16110:51;16178:18;;85334:65:0::2;15857:345:1::0;85334:65:0::2;85445:17;85495:15;85466:9;:26;;;:44;85465:97;;85561:1;85465:97;;;85543:15;85514:9;:26;;;:44;;;;:::i;:::-;85445:117:::0;-1:-1:-1;85573:16:0::2;85592:31;85608:15;85592:13:::0;:31:::2;:::i;:::-;85573:50;;85729:9;85718:8;:20;85710:57;;;::::0;::::2;::::0;;16409:2:1;85710:57:0::2;::::0;::::2;16391:21:1::0;16448:2;16428:18;;;16421:30;16487:26;16467:18;;;16460:54;16531:18;;85710:57:0::2;16207:348:1::0;85710:57:0::2;85798:13;;85786:8;:25;;85778:64;;;::::0;::::2;::::0;;16762:2:1;85778:64:0::2;::::0;::::2;16744:21:1::0;16801:2;16781:18;;;16774:30;16840:28;16820:18;;;16813:56;16886:18;;85778:64:0::2;16560:350:1::0;85778:64:0::2;85873:28;;85861:8;:40;;85853:80;;;::::0;::::2;::::0;;17117:2:1;85853:80:0::2;::::0;::::2;17099:21:1::0;17156:2;17136:18;;;17129:30;17195:29;17175:18;;;17168:57;17242:18;;85853:80:0::2;16915:351:1::0;85853:80:0::2;86017:174;;;;;;;;86043:6;86017:174;;;;86064:15;86017:174;;;;86094:9;:19;;;86017:174;;;;86128:13;86017:174;;;;86156:24;86171:8;86156:14;:24::i;:::-;86017:174:::0;;85988:10:::2;85975:24;::::0;;;:12:::2;:24;::::0;;;;:39;;86000:13;;85975:39;::::2;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86260:41;86283:10;86295:5;86260:22;:41::i;:::-;86319:74;::::0;;17502:25:1;;;17558:2;17543:18;;17536:34;;;86362:15:0::2;17586:18:1::0;;;17579:34;17644:2;17629:18;;17622:34;;;86319:74:0;;86332:10:::2;::::0;86319:74:::2;::::0;;;;;17489:3:1;86319:74:0;;::::2;-1:-1:-1::0;;21588:1:0;22550:7;:22;-1:-1:-1;;;;;;85044:1357:0:o;38064:166::-;38172:26;;;38126:7;38172:26;;;:17;:26;;;;;;38154:15;;28117:4;;38154:44;;;:::i;55414:483::-;31469:5;;55580:20;;31469:5;;31455:10;:19;;:74;;;31478:51;31496:10;31508:20;31478:17;:51::i;:::-;31447:107;;;;;;;13743:2:1;31447:107:0;;;13725:21:1;13782:2;13762:18;;;13755:30;13821:22;13801:18;;;13794:50;13861:18;;31447:107:0;13541:344:1;31447:107:0;55631:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;55613:17:::1;:61:::0;;55677:9;;55631:42;55613:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;55760:25;55697:16;55714:20;:42;55735:20;55714:42;;;;;;;;;;;;;;;;55697:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;55815:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;55796:18:::1;:62:::0;;55861:28;;55815:42;55796:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;55414:483:::0;;;;;:::o;42521:800::-;42601:34;;;;;;;:19;:34;;;;;;;;42593:60;;;;;;;17869:2:1;42593:60:0;;;17851:21:1;17908:2;17888:18;;;17881:30;17947:15;17927:18;;;17920:43;17980:18;;42593:60:0;17667:337:1;42593:60:0;42672:36;;;;;;;:21;:36;;;;;;;;42709:10;42672:48;;;;;;;;;;42664:90;;;;;;;18211:2:1;42664:90:0;;;18193:21:1;18250:2;18230:18;;;18223:30;18289:31;18269:18;;;18262:59;18338:18;;42664:90:0;18009:353:1;42664:90:0;42900:10;42849:22;42874:37;;;:25;:37;;;;;;;;42926:28;;42922:182;;43081:10;43063:29;;;;:17;:29;;;;;;;;;;43026:33;;;;:17;:33;;;;;:66;;43063:29;;43026:33;;:66;;43063:29;;43026:66;:::i;:::-;;;;-1:-1:-1;;42922:182:0;43172:10;43146:37;;;;:25;:37;;;;;;;:53;;;;:37;:53;;;;;;;;43284:17;:29;;;;;;43248:32;;;:17;:32;;;;;:65;;43284:29;;43248:32;;:65;;43284:29;;43248:65;:::i;:::-;;;;-1:-1:-1;;;;42521:800:0:o;55972:207::-;31469:5;;56080:20;;31469:5;;31455:10;:19;;:74;;;31478:51;31496:10;31508:20;31478:17;:51::i;:::-;31447:107;;;;;;;13743:2:1;31447:107:0;;;13725:21:1;13782:2;13762:18;;;13755:30;13821:22;13801:18;;;13794:50;13861:18;;31447:107:0;13541:344:1;31447:107:0;-1:-1:-1;56113:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;55972:207::o;52922:97::-;31266:5;;;;31252:10;:19;;:79;;-1:-1:-1;31289:42:0;31275:10;:56;31252:79;31244:113;;;;;;;12289:2:1;31244:113:0;;;12271:21:1;12328:2;12308:18;;;12301:30;12367:23;12347:18;;;12340:51;12408:18;;31244:113:0;12087:345:1;31244:113:0;52997:14:::1;::::0;;52979:32;;::::1;52997:14;::::0;;::::1;52996:15;52979:32;::::0;;52922:97::o;88799:259::-;88899:7;21632:1;22238:7;;:19;22230:63;;;;;;;11386:2:1;22230:63:0;;;11368:21:1;11425:2;11405:18;;;11398:30;11464:33;11444:18;;;11437:61;11515:18;;22230:63:0;11184:355:1;22230:63:0;21632:1;22371:18;;88927:17:::1;::::0;::::1;::::0;::::1;;;:26;88919:57;;;::::0;::::1;::::0;;18569:2:1;88919:57:0::1;::::0;::::1;18551:21:1::0;18608:2;18588:18;;;18581:30;18647:20;18627:18;;;18620:48;18685:18;;88919:57:0::1;18367:342:1::0;88919:57:0::1;88994:56;89010:10;89022:19;89043:6;88994:15;:56::i;41796:610::-:0;41895:10;41875:31;;;;:19;:31;;;;;;;;41867:57;;;;;;;17869:2:1;41867:57:0;;;17851:21:1;17908:2;17888:18;;;17881:30;17947:15;17927:18;;;17920:43;17980:18;;41867:57:0;17667:337:1;41867:57:0;42010:10;41988:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;41987:50;41935:102;;;;;;;42140:41;;;;;;;;:55;42136:263;;42211:41;;;42263:1;42211:41;;;:25;:41;;;;;;;:54;;;;;;42354:17;:33;;;;;;42339:10;42321:29;;:17;:29;;;;;:66;;42354:33;;42321:29;;:66;;42354:33;;42321:66;:::i;:::-;;;;-1:-1:-1;;42136:263:0;41796:610;:::o;33913:452::-;33974:16;34003:32;34038:16;34055:9;34038:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;34080:38:0;;34076:282;;34261:4;34219:27;34247:9;34219:38;;;;;;;;:::i;:::-;;;;;;;;;34168:24;34147:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;34146:119;;;;:::i;:::-;34135:130;;34076:282;;;34318:17;34336:9;34318:28;;;;;;;;:::i;:::-;;;;;;;;;34307:39;;33992:373;33913:452;;;:::o;51208:761::-;51325:9;51320:642;51344:16;:23;51340:27;;51320:642;;;51389:32;51424:16;51441:1;51424:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;51462:38:0;;51458:493;;51525:12;:61;;;;51560:22;51583:1;51560:25;;;;;;;;:::i;:::-;;;;;;;;;51542:15;:43;51525:61;51521:415;;;51700:106;;;;;51783:4;51700:106;;;18888:74:1;51790:15:0;18978:18:1;;;18971:34;51700:74:0;;;;;;18861:18:1;;51700:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51667:27;51695:1;51667:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;51878:24;51857:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51829:22;51852:1;51829:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;51521:415;-1:-1:-1;51369:3:0;;;;:::i;:::-;;;;51320:642;;54379:958;31266:5;;;;31252:10;:19;;:79;;-1:-1:-1;31289:42:0;31275:10;:56;31252:79;31244:113;;;;;;;12289:2:1;31244:113:0;;;12271:21:1;12328:2;12308:18;;;12301:30;12367:23;12347:18;;;12340:51;12408:18;;31244:113:0;12087:345:1;31244:113:0;54788:13;;28117:4:::1;-1:-1:-1::0;54788:37:0::1;54780:69;;;::::0;::::1;::::0;;19218:2:1;54780:69:0::1;::::0;::::1;19200:21:1::0;19257:2;19237:18;;;19230:30;19296:21;19276:18;;;19269:49;19335:18;;54780:69:0::1;19016:343:1::0;54780:69:0::1;54973:13:::0;;::::1;::::0;54990:1:::1;-1:-1:-1::0;54973:18:0;::::1;::::0;54972:44:::1;;-1:-1:-1::0;54997:13:0;;::::1;::::0;55014:1:::1;-1:-1:-1::0;54997:18:0::1;54972:44;54964:69;;;::::0;::::1;::::0;;19907:2:1;54964:69:0::1;::::0;::::1;19889:21:1::0;19946:2;19926:18;;;19919:30;19985:14;19965:18;;;19958:42;20017:18;;54964:69:0::1;19705:336:1::0;54964:69:0::1;55068:13:::0;;55046:19:::1;:35:::0;55068:13:::1;55115::::0;::::1;::::0;55092:20:::1;:36:::0;55170:13;;::::1;::::0;55139:28:::1;:44:::0;55221:13;;::::1;::::0;55194:24:::1;:40:::0;55276:13;;::::1;::::0;55245:28:::1;:44:::0;55316:13;::::1;::::0;55300::::1;:29:::0;54379:958::o;51977:363::-;52060:25;52079:5;52060:18;:25::i;:::-;52155:16;:14;:16::i;:::-;52137:15;:34;52207:12;;52188:15;:31;52184:149;;52236:14;:12;:14::i;:::-;51977:363::o;52184:149::-;52292:29;:27;:29::i;9783:106::-;9841:7;9872:1;9868;:5;:13;;9880:1;9868:13;;;9876:1;9868:13;9861:20;9783:106;-1:-1:-1;;;9783:106:0:o;86922:1705::-;87168:7;87137:14;87153:4;31660:41;31683:7;31692:8;31660:22;:41::i;:::-;87196:13:::1;::::0;;;::::1;;;:22;87188:49;;;::::0;::::1;::::0;;20248:2:1;87188:49:0::1;::::0;::::1;20230:21:1::0;20287:2;20267:18;;;20260:30;20326:16;20306:18;;;20299:44;20360:18;;87188:49:0::1;20046:338:1::0;87188:49:0::1;87264:13;;87256:4;:21;;87248:60;;;::::0;::::1;::::0;;16762:2:1;87248:60:0::1;::::0;::::1;16744:21:1::0;16801:2;16781:18;;;16774:30;16840:28;16820:18;;;16813:56;16886:18;;87248:60:0::1;16560:350:1::0;87248:60:0::1;87335:28;;87327:4;:36;;87319:75;;;::::0;::::1;::::0;;17117:2:1;87319:75:0::1;::::0;::::1;17099:21:1::0;17156:2;17136:18;;;17129:30;17195:29;17175:18;;;17168:57;17242:18;;87319:75:0::1;16915:351:1::0;87319:75:0::1;87517:12;::::0;87477:96:::1;::::0;87517:12;;::::1;;;87532:14:::0;87556:4:::1;87563:9:::0;87477:31:::1;:96::i;:::-;87633:23;87659:20;87674:4;87659:14;:20::i;:::-;87778:33;::::0;::::1;87690:14;87778:33:::0;;;:17:::1;:33;::::0;;;;;;;;87717:95;;20635:66:1;20622:2;20618:15;;;20614:88;87717:95:0;;::::1;20602:101:1::0;;;;20719:12;;;20712:28;;;20756:12;;;20749:28;;;20793:12;;;20786:28;87633:46:0;;-1:-1:-1;87690:14:0;20830:13:1;;87717:95:0::1;::::0;;;;;::::1;::::0;;;;;;87707:106;;87717:95:::1;87707:106:::0;;::::1;::::0;87870:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;87904:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;87707:106;;-1:-1:-1;87870:28:0;87904:164;;;88005:22:::1;88023:4:::0;87951:15;88005:22:::1;:::i;:::-;87904:164:::0;;::::1;::::0;;::::1;::::0;;;87870:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;87870: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;88113:23:::1;:36:::0;;88140:9;;-1:-1:-1;88113:36:0::1;::::0;88140:9;;88113:36:::1;:::i;:::-;::::0;;;-1:-1:-1;;88160:33:0::1;::::0;::::1;;::::0;;;:17:::1;:33;::::0;;;;:46;;88197:9;;88160:33;:46:::1;::::0;88197:9;;88160:46:::1;:::i;:::-;::::0;;;-1:-1:-1;88232:17:0::1;::::0;-1:-1:-1;88252:27:0::1;88264:14:::0;88252:11:::1;:27::i;:::-;88232:47:::0;-1:-1:-1;88298:23:0::1;::::0;::::1;::::0;88294:70:::1;;88323:28;::::0;::::1;;::::0;;;:17:::1;:28;::::0;;;;:41;;88355:9;;88323:28;:41:::1;::::0;88355:9;;88323:41:::1;:::i;:::-;::::0;;;-1:-1:-1;;88294:70:0::1;88217:159;88462:45;88485:14;88501:5;88462:22;:45::i;:::-;88525:68;::::0;;21085:25:1;;;21141:2;21126:18;;21119:34;;;21169:18;;;21162:34;;;88525:68:0::1;21232:55:1::0;;;21227:2;21212:18;;21205:83;88525:68:0;::::1;::::0;::::1;::::0;21072:3:1;21057:19;88525:68:0::1;;;;;;;88613:6:::0;86922:1705;-1:-1:-1;;;;;;;;;86922:1705:0:o;45017:585::-;45079:21;;;;45075:520;;45156:27;45186:15;45193:7;45186:6;:15::i;:::-;45156:45;;45264:9;45259:118;45283:10;:17;45279:1;:21;45259:118;;;45348:10;45359:1;45348:13;;;;;;;;:::i;:::-;;;;;;;;;;;;45326:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;45343:1;45302:3;45343:1;45302:3;:::i;:::-;;;;45259:118;;;;45444:9;45439:145;45463:10;:17;45459:1;:21;45439:145;;;45544:21;45566:1;45544:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;45506:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;45539:1;45482:3;45539:1;45482:3;:::i;:::-;;;;45439:145;;33772:133;33831:7;33858:39;33867:15;33884:12;;33858:8;:39::i;:::-;33851:46;;33772:133;:::o;46662:1194::-;46810:31;46785:8;46795:4;31660:41;31683:7;31692:8;31660:22;:41::i;:::-;46940:29:::1;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;46972:15:::1;46940:47:::0;;47070:23:::1;::::0;;;::::1;;;:32;47062:70;;;::::0;::::1;::::0;;11935:2:1;47062:70:0::1;::::0;::::1;11917:21:1::0;11974:2;11954:18;;;11947:30;12013:27;11993:18;;;11986:55;12058:18;;47062:70:0::1;11733:349:1::0;47062:70:0::1;47244:12;:19:::0;47230:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;47230:34:0::1;;47213:51;;47282:9;47277:419;47301:12;:19:::0;47297:23;::::1;47277:419;;;47362:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;47342:17;;:14;;47380:1;;47342:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;47397:17:::1;::::0;::::1;47420:1;47397:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;47440:17;;:14;;47415:1;;47440:17;::::1;;;;;:::i;:::-;;;;;;;:21;47436:249;;;47482:84;47510:12;47523:1;47510:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;47527:19;47548:14;47563:1;47548:17;;;;;;;;:::i;:::-;;;;;;;47482:27;:84::i;:::-;47603:8;47592:77;;;47613:14;47628:1;47613:17;;;;;;;;:::i;:::-;;;;;;;47632:12;47645:1;47632:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;47592:77:::1;::::0;;21501:25:1;;;47632:15:0::1;::::0;;::::1;21603:18:1::0;;;21596:43;;;;21675:15;;21655:18;;;21648:43;21489:2;21474:18;47592:77:0::1;;;;;;;47436:249;47322:3:::0;::::1;::::0;::::1;:::i;:::-;;;;47277:419;;;;46662:1194:::0;;;;;;;:::o;18949:361::-;19144:45;;;19133:10;18906:55:1;;;19144:45:0;;;18888:74:1;18978:18;;;;18971:34;;;19144:45:0;;;;;;;;;;18861:18:1;;;;19144:45:0;;;;;;;;;;;;;19133:57;;-1:-1:-1;;;;19133:10:0;;;;:57;;19144:45;19133:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19097:93;;;;19209:7;:57;;;;-1:-1:-1;19221:11:0;;:16;;:44;;;19252:4;19241:24;;;;;;;;;;;;:::i;:::-;19201:101;;;;;;;22701:2:1;19201:101:0;;;22683:21:1;22740:2;22720:18;;;22713:30;22779:33;22759:18;;;22752:61;22830:18;;19201:101:0;22499:355:1;83094:508:0;83176:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83176:31:0;83209:15;;83237:280;83261:28;;;;;;;:12;:28;;;;;:35;83257:39;;83237:280;;;83332:28;;;;;;;:12;:28;;;;;:31;;83361:1;;83332:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;83322:6;:48;83318:188;;83405:28;;;;;;;:12;:28;;;;;:31;;83434:1;;83405:31;;;;;;:::i;:::-;;;;;;;;;;;83390:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83465:1;83455:11;;83485:5;;83318:188;83298:3;;;;:::i;:::-;;;;83237:280;;;-1:-1:-1;83535:19:0;;:29;;83527:57;;;;;;;23061:2:1;83527:57:0;;;23043:21:1;23100:2;23080:18;;;23073:30;23139:17;23119:18;;;23112:45;23174:18;;83527:57:0;22859:339:1;83527:57:0;83094:508;;;;;:::o;19318:402::-;19543:51;;;19532:10;23484:15:1;;;19543:51:0;;;23466:34:1;23536:15;;;23516:18;;;23509:43;23568:18;;;;23561:34;;;19543:51:0;;;;;;;;;;23378:18:1;;;;19543:51:0;;;;;;;;;;;;;19532:63;;-1:-1:-1;;;;19532:10:0;;;;:63;;19543:51;19532:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19496:99;;;;19614:7;:57;;;;-1:-1:-1;19626:11:0;;:16;;:44;;;19657:4;19646:24;;;;;;;;;;;;:::i;:::-;19606:106;;;;;;;23808:2:1;19606:106:0;;;23790:21:1;23847:2;23827:18;;;23820:30;23886:34;23866:18;;;23859:62;23957:6;23937:18;;;23930:34;23981:19;;19606:106:0;23606:400:1;19606:106:0;19406:314;;19318:402;;;;:::o;89193:1555::-;89339:7;89422:53;89433:14;89449:19;89470:4;89422:10;:53::i;:::-;;89529:28;89559:21;89584:33;89594:14;89610:6;89584:9;:33::i;:::-;89528:89;;;;89655:9;:26;;;89636:15;:45;;:71;;;-1:-1:-1;89685:14:0;;;;:22;;:14;:22;89636:71;89628:106;;;;;;;24213:2:1;89628:106:0;;;24195:21:1;24252:2;24232:18;;;24225:30;24291:24;24271:18;;;24264:52;24333:18;;89628:106:0;24011:346:1;89628:106:0;89765:19;;;;89801:13;;89797:915;;89981:12;;89945:82;;89981:12;;;;;89996:19;90017:9;89945:27;:82::i;:::-;90106:9;90079:23;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;90130:33:0;;;;;;;:17;:33;;;;;:46;;90167:9;;90130:33;:46;;90167:9;;90130:46;:::i;:::-;;;;-1:-1:-1;90210:17:0;;-1:-1:-1;90230:27:0;90242:14;90230:11;:27::i;:::-;90210:47;-1:-1:-1;90280:23:0;;;;90276:70;;90305:28;;;;;;;:17;:28;;;;;:41;;90337:9;;90305:28;:41;;90337:9;;90305:41;:::i;:::-;;;;-1:-1:-1;;90276:70:0;-1:-1:-1;90433:28:0;;;;;;;:12;:28;;;;;:43;;90462:13;;90433:43;;;;;;:::i;:::-;;;;;;;;;;;;;90426:50;;;;;;;;;;;;;;;;;;;;;;;;;;90563:45;;90586:14;;90563:22;:45::i;:::-;90630:70;;;24564:25:1;;;24620:2;24605:18;;24598:34;;;90630:70:0;24668:55:1;;;24648:18;;;24641:83;90630:70:0;;;;;;;;;;;24552:2:1;90630:70:0;;;89797:915;90731:9;89193:1555;-1:-1:-1;;;;;;89193:1555:0:o;47943:2814::-;48064:9;48059:327;48083:18;:25;48079:29;;48059:327;;;48130:34;48167:18;48186:1;48167:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;48207:40:0;;48203:172;;48268:91;;;;;48353:4;48268:91;;;3721:74:1;48268:76:0;;;;;;3694:18:1;;48268:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;48203:172;-1:-1:-1;48110:3:0;;;;:::i;:::-;;;;48059:327;;;;48746:27;29633:6;48802:12;;48784:15;:30;;;;:::i;:::-;48776:57;;;;:::i;:::-;48746:87;;48972:9;48967:284;48991:12;:19;48987:23;;48967:284;;;49113:12;49126:1;49113:15;;;;;;;;:::i;:::-;;;;;;;;;;;49106:48;;;;;49148:4;49106:48;;;3721:74:1;49113:15:0;;;;;49106:33;;3694:18:1;;49106:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49077:23;:19;49099:1;49077:23;:::i;:::-;29633:6;49041:14;49053:1;49041:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;49040:114;;49220:12;49233:1;49220:15;;;;;;;;:::i;:::-;;;;;;;;;;;;49163:73;;;25227:34:1;49163:73:0;;;25215:47:1;;;;25292:6;25278:12;;;25271:28;25337:2;25333:15;;;25315:12;;;25308:110;25434:12;;49163:73:0;;;;;;;;;;;;49032:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;49012:3:0;;;;:::i;:::-;;;;48967:284;;;-1:-1:-1;29633:6:0;49463:23;:19;49485:1;49463:23;:::i;:::-;49462:43;;;;:::i;:::-;49446:12;;:60;;;;:::i;:::-;49431:12;:75;49559:29;:27;:29::i;:::-;49658:16;:14;:16::i;:::-;49640:15;:34;-1:-1:-1;47943:2814:0:o;50765:435::-;50852:34;50889:17;:15;:17::i;:::-;50852:54;;50969:9;50964:133;50988:21;:28;50984:32;;50964:133;;;51065:17;51083:1;51065:20;;;;;;;;:::i;:::-;;;;;;;51038:21;51060:1;51038:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;51018:3;;;;:::i;:::-;;;;50964:133;;;;51166:26;:24;:26::i;:::-;51149:14;:43;-1:-1:-1;50765: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;3806:260::-;3874:6;3882;3935:2;3923:9;3914:7;3910:23;3906:32;3903:52;;;3951:1;3948;3941:12;3903:52;3974:29;3993:9;3974:29;:::i;:::-;3964:39;;4022:38;4056:2;4045:9;4041:18;4022:38;:::i;:::-;4012:48;;3806:260;;;;;:::o;4745:118::-;4831:5;4824:13;4817:21;4810:5;4807:32;4797:60;;4853:1;4850;4843:12;4868:315;4933:6;4941;4994:2;4982:9;4973:7;4969:23;4965:32;4962:52;;;5010:1;5007;5000:12;4962:52;5033:29;5052:9;5033:29;:::i;:::-;5023:39;;5112:2;5101:9;5097:18;5084:32;5125:28;5147:5;5125:28;:::i;:::-;5172:5;5162:15;;;4868:315;;;;;:::o;5453:254::-;5521:6;5529;5582:2;5570:9;5561:7;5557:23;5553:32;5550:52;;;5598:1;5595;5588:12;5550:52;5621:29;5640:9;5621:29;:::i;:::-;5611:39;5697:2;5682:18;;;;5669:32;;-1:-1:-1;;;5453:254:1:o;6937:511::-;7005:6;7013;7021;7074:2;7062:9;7053:7;7049:23;7045:32;7042:52;;;7090:1;7087;7080:12;7042:52;7129:9;7116:23;7148:28;7170:5;7148:28;:::i;:::-;7195:5;-1:-1:-1;7252:2:1;7237:18;;7224:32;7265:30;7224:32;7265:30;:::i;:::-;7314:7;-1:-1:-1;7373:2:1;7358:18;;7345:32;7386:30;7345:32;7386:30;:::i;:::-;7435:7;7425:17;;;6937:511;;;;;:::o;7453:403::-;7539:6;7547;7555;7563;7616:3;7604:9;7595:7;7591:23;7587:33;7584:53;;;7633:1;7630;7623:12;7584:53;7656:29;7675:9;7656:29;:::i;:::-;7646:39;;7732:2;7721:9;7717:18;7704:32;7694:42;;7755:38;7789:2;7778:9;7774:18;7755:38;:::i;:::-;7745:48;;7812:38;7846:2;7835:9;7831:18;7812:38;:::i;:::-;7802:48;;7453:403;;;;;;;:::o;7861:254::-;7929:6;7937;7990:2;7978:9;7969:7;7965:23;7961:32;7958:52;;;8006:1;8003;7996:12;7958:52;8042:9;8029:23;8019:33;;8071:38;8105:2;8094:9;8090:18;8071:38;:::i;8120:241::-;8176:6;8229:2;8217:9;8208:7;8204:23;8200:32;8197:52;;;8245:1;8242;8235:12;8197:52;8284:9;8271:23;8303:28;8325:5;8303:28;:::i;8366:184::-;8418:77;8415:1;8408:88;8515:4;8512:1;8505:15;8539:4;8536:1;8529:15;8555:915;8637:6;8690:3;8678:9;8669:7;8665:23;8661:33;8658:53;;;8707:1;8704;8697:12;8658:53;8756:7;8749:4;8738:9;8734:20;8730:34;8720:62;;8778:1;8775;8768:12;8720:62;8811:2;8805:9;8853:3;8845:6;8841:16;8923:6;8911:10;8908:22;8887:18;8875:10;8872:34;8869:62;8866:242;;;8964:77;8961:1;8954:88;9065:4;9062:1;9055:15;9093:4;9090:1;9083:15;8866:242;9124:2;9117:22;9159:6;9203:3;9188:19;;9219;;;9216:39;;;9251:1;9248;9241:12;9216:39;9275:9;9293:146;9309:6;9304:3;9301:15;9293:146;;;9377:17;;9365:30;;9424:4;9415:14;;;;9326;9293:146;;;-1:-1:-1;9458:6:1;;8555:915;-1:-1:-1;;;;;8555:915:1:o;9475:184::-;9527:77;9524:1;9517:88;9624:4;9621:1;9614:15;9648:4;9645:1;9638:15;9664:184;9716:77;9713:1;9706:88;9813:4;9810:1;9803:15;9837:4;9834:1;9827:15;9853:128;9920:9;;;9941:11;;;9938:37;;;9955:18;;:::i;9986:168::-;10059:9;;;10090;;10107:15;;;10101:22;;10087:37;10077:71;;10128:18;;:::i;10159:274::-;10199:1;10225;10215:189;;10260:77;10257:1;10250:88;10361:4;10358:1;10351:15;10389:4;10386:1;10379:15;10215:189;-1:-1:-1;10418:9:1;;10159:274::o;10438:125::-;10503:9;;;10524:10;;;10521:36;;;10537:18;;:::i;10568:195::-;10607:3;10638:66;10631:5;10628:77;10625:103;;10708:18;;:::i;:::-;-1:-1:-1;10755:1:1;10744:13;;10568:195::o;11544:184::-;11614:6;11667:2;11655:9;11646:7;11642:23;11638:32;11635:52;;;11683:1;11680;11673:12;11635:52;-1:-1:-1;11706:16:1;;11544:184;-1:-1:-1;11544:184:1:o;14843:179::-;14921:13;;14974:22;14963:34;;14953:45;;14943:73;;15012:1;15009;15002:12;15027:473;15130:6;15138;15146;15154;15162;15215:3;15203:9;15194:7;15190:23;15186:33;15183:53;;;15232:1;15229;15222:12;15183:53;15255:39;15284:9;15255:39;:::i;:::-;15245:49;;15334:2;15323:9;15319:18;15313:25;15303:35;;15378:2;15367:9;15363:18;15357:25;15347:35;;15422:2;15411:9;15407:18;15401:25;15391:35;;15445:49;15489:3;15478:9;15474:19;15445:49;:::i;:::-;15435:59;;15027:473;;;;;;;;:::o;21702:250::-;21787:1;21797:113;21811:6;21808:1;21805:13;21797:113;;;21887:11;;;21881:18;21868:11;;;21861:39;21833:2;21826:10;21797:113;;;-1:-1:-1;;21944:1:1;21926:16;;21919:27;21702:250::o;21957:287::-;22086:3;22124:6;22118:13;22140:66;22199:6;22194:3;22187:4;22179:6;22175:17;22140:66;:::i;:::-;22222:16;;;;;21957:287;-1:-1:-1;;21957:287:1:o;22249:245::-;22316:6;22369:2;22357:9;22348:7;22344:23;22340:32;22337:52;;;22385:1;22382;22375:12;22337:52;22417:9;22411:16;22436:28;22458:5;22436:28;:::i;24735:245::-;24814:6;24822;24875:2;24863:9;24854:7;24850:23;24846:32;24843:52;;;24891:1;24888;24881:12;24843:52;-1:-1:-1;;24914:16:1;;24970:2;24955:18;;;24949:25;24914:16;;24949:25;;-1:-1:-1;24735:245:1:o;25457:455::-;25606:2;25595:9;25588:21;25569:4;25638:6;25632:13;25681:6;25676:2;25665:9;25661:18;25654:34;25697:79;25769:6;25764:2;25753:9;25749:18;25744:2;25736:6;25732:15;25697:79;:::i;:::-;25828:2;25816:15;25833:66;25812:88;25797:104;;;;25903:2;25793:113;;25457:455;-1:-1:-1;;25457:455:1:o
Swarm Source
ipfs://85b8ef294481f9db096da0d0d8a25492296a2803a77cd8dc0943d23759b00f11
Loading...
Loading
Loading...
Loading
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.