More Info
Private Name Tags
ContractCreator
Latest 17 from a total of 17 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Sync | 20861730 | 118 days ago | IN | 0 ETH | 0.00387031 | ||||
Sync | 20602463 | 155 days ago | IN | 0 ETH | 0.00051683 | ||||
Sync | 20576165 | 158 days ago | IN | 0 ETH | 0.00018957 | ||||
Sync | 20476933 | 172 days ago | IN | 0 ETH | 0.00058593 | ||||
Sync | 20454748 | 175 days ago | IN | 0 ETH | 0.00016859 | ||||
Sync | 20369537 | 187 days ago | IN | 0 ETH | 0.00253222 | ||||
Sync | 20304984 | 196 days ago | IN | 0 ETH | 0.00151308 | ||||
Sync | 20248867 | 204 days ago | IN | 0 ETH | 0.00176385 | ||||
Sync | 20125414 | 221 days ago | IN | 0 ETH | 0.00043391 | ||||
Sync | 20089190 | 226 days ago | IN | 0 ETH | 0.00330461 | ||||
Sync | 20024372 | 235 days ago | IN | 0 ETH | 0.00454101 | ||||
Sync | 19881320 | 255 days ago | IN | 0 ETH | 0.00285749 | ||||
Sync | 19860649 | 258 days ago | IN | 0 ETH | 0.00184382 | ||||
Sync | 19783585 | 269 days ago | IN | 0 ETH | 0.00904559 | ||||
Get Reward | 19613724 | 293 days ago | IN | 0 ETH | 0.00906228 | ||||
Sync | 19613721 | 293 days ago | IN | 0 ETH | 0.00308454 | ||||
Stake Locked | 19613720 | 293 days ago | IN | 0 ETH | 0.02049924 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-04-08 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.19.4 https://hardhat.org // File contracts/Common/Context.sol // Original license: SPDX_License_Identifier: MIT /* * @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 // Original license: SPDX_License_Identifier: MIT /** * @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 // Original license: SPDX_License_Identifier: MIT /** * @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/Misc_AMOs/convex/IConvexStakingWrapperFrax.sol // Original license: SPDX_License_Identifier: MIT interface IConvexStakingWrapperFrax { function addRewards ( ) external; function addTokenReward ( address _token ) 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 distroContract ( ) external view returns ( address ); function distroImplementation ( ) external view returns ( address ); function distroSealed ( ) external view returns ( bool ); function earmarkRewards ( ) external returns ( bool ); function factory ( ) external view returns ( address ); function getReward ( address _account, address _forwardTo ) external; function getReward ( address _account ) external; function increaseAllowance ( address spender, uint256 addedValue ) external returns ( bool ); function initialize ( uint256 _poolId ) external; function invalidateReward ( address _token ) 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 proxyFactory ( ) external view returns ( address ); function registeredRewards ( address ) external view returns ( uint256 ); function renounceOwnership ( ) external; function rewardHook ( ) external view returns ( address ); function rewardLength ( ) external view returns ( uint256 ); function rewardRedirect ( address ) external view returns ( address ); function rewards ( uint256 ) external view returns ( address reward_token, address reward_pool, uint256 reward_integral, uint256 reward_remaining ); function sealDistributor ( ) external; function setApprovals ( ) external; function setDistributor ( address _distro ) external; function setHook ( address _hook ) external; function setRewardRedirect ( address _to ) 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 _account ) external returns ( bool ); function withdraw ( uint256 _amount ) external; function withdrawAndUnwrap ( uint256 _amount ) external; } // File contracts/Misc_AMOs/curve/I2pool.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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 price_oracle() 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 // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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/Curve/IFraxGaugeController.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // 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/Curve/IFraxGaugeFXSRewardsDistributor.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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/IveFXS.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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/Math/Math.sol // Original license: SPDX_License_Identifier: MIT /** * @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/Misc_AMOs/convex/IConvexBaseRewardPool.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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/Owned.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // 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/Uniswap/TransferHelper.sol // Original license: SPDX_License_Identifier: MIT // 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 // Original license: SPDX_License_Identifier: MIT /** * @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/FraxUnifiedFarmTemplate.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ====================== 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 // Balancer // ==================== // import "../Misc_AMOs/balancer/IAuraDeposit.sol"; // import "../Misc_AMOs/balancer/IAuraDepositVault.sol"; // BUNNI // ==================== // import "../Misc_AMOs/bunni/IBunniGauge.sol"; // import "../Misc_AMOs/bunni/IBunniLens.sol"; // import "../Misc_AMOs/bunni/IBunniMinter.sol"; // CONVEX // ==================== contract FraxUnifiedFarmTemplate is Owned, ReentrancyGuard { // -------------------- VARIES -------------------- // Balancer // IAuraDeposit public stakingToken; // IAuraDepositVault public aura_deposit_vault = IAuraDepositVault(0xE557658e3D13d074961265756dC2eFB6c903A763); // Bunni // IBunniGauge public stakingToken; // IBunniLens public lens = IBunniLens(0xb73F303472C4fD4FF3B9f59ce0F9b13E47fbfD19); // IBunniMinter public minter = IBunniMinter(0xF087521Ffca0Fa8A43F5C445773aB37C5f574DA0); /* ========== STATE VARIABLES ========== */ // Instances IveFXS private constant veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0); // Frax related address internal constant frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e; /// @notice fraxPerLPToken is a public view function, although doesn't show the stored value uint256 public fraxPerLPStored; // Constant for various precisions uint256 internal constant MULTIPLIER_PRECISION = 1e18; // Time tracking /// @notice Ending timestamp for the current period uint256 public periodFinish; /// @notice Timestamp of the last update - when this period started 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 * 1095 * 86400; // 3 years // uint256 public lock_time_for_max_multiplier = 2 * 86400; // 2 days uint256 public lock_time_min = 1; // 1 seconds. If 0, calcCurrLockMultiplier could div by 0 // 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 /// @notice token addr -> manager addr mapping(address => address) public rewardManagers; address[] internal rewardTokens; address[] internal gaugeControllers; address[] internal rewardDistributors; uint256[] internal rewardRatesManual; mapping(address => bool) internal isRewardToken; /// @notice token addr -> token index mapping(address => uint256) public rewardTokenAddrToIdx; // 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; /// @notice Keeps track of LP balances proxy-wide. Needed to make sure the proxy boost is kept in line mapping(address => uint256) public proxy_lp_balances; /// @notice Stakers set which proxy(s) they want to use /// @dev Keep public so users can see on the frontend if they have a proxy mapping(address => address) public staker_designated_proxies; // 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 // For emergencies if a token is overemitted or something else. Only callable once. // Bypasses certain logic, which will cause reward calculations to be off // But the goal is for the users to recover LP, and they couldn't claim the erroneous rewards anyways. // Reward reimbursement claims would be handled with pre-issue earned() snapshots and a claim contract, or similar. bool public withdrawalOnlyShutdown; // Version string public version = "1.0.6"; /* ========== 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, false); _; } /* ========== 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; // Add to the mapping isRewardToken[_rewardTokens[i]] = true; // 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; // Sync the first period finish here with the gauge's // periodFinish = IFraxGaugeController(gaugeControllers[0]).time_total(); periodFinish = IFraxGaugeController(0x3669C421b77340B2979d1A00a792CC2ee0FcE737).time_total(); } /* ============= VIEWS ============= */ // ------ REWARD RELATED ------ /// @notice Checks if the caller is a manager for the reward token /// @param caller_addr The address of the caller /// @param reward_token_addr The address of the reward token /// @return bool True if the caller is a manager for the reward token function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool){ if (!isRewardToken[reward_token_addr]) return false; else if (caller_addr == address(0) || reward_token_addr == address(0)) return false; else if (caller_addr == owner) return true; // Contract owner else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager return false; } /// @notice Gets all the reward tokens this contract handles /// @return rewardTokens_ The reward tokens array 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); } /// @notice The amount of reward tokens being paid out per second this period /// @param token_idx The index of the reward token /// @return rwd_rate The reward rate 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; } } /// @notice The amount of reward tokens an account has earned / accrued /// @dev In the edge-case of one of the account's stake expiring since the last claim, this will /// @param account The account to check /// @return new_earned Array of reward token amounts earned by the account 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]; } } } /// @notice The total reward tokens emitted in the given period /// @return rewards_per_duration_arr Array of reward token amounts emitted in the current 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 ------ /// @notice The farm's total locked liquidity / LP tokens /// @return The total locked liquidity function totalLiquidityLocked() external view returns (uint256) { return _total_liquidity_locked; } /// @notice A user's locked liquidity / LP tokens /// @param account The address of the account /// @return The locked liquidity function lockedLiquidityOf(address account) external view returns (uint256) { return _locked_liquidity[account]; } /// @notice The farm's total combined weight of all users /// @return The total combined weight function totalCombinedWeight() external view returns (uint256) { return _total_combined_weight; } /// @notice Total 'balance' used for calculating the percent of the pool the account owns /// @notice Takes into account the locked stake time multiplier and veFXS multiplier /// @param account The address of the account /// @return The combined weight function combinedWeightOf(address account) external view returns (uint256) { return _combined_weights[account]; } /// @notice Calculates the combined weight for an account /// @notice Must be overriden by the child contract /// @dev account The address of the 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 ------ /// @notice Reads the lock boost multiplier for a given duration /// @param secs The duration of the lock in seconds /// @return The multiplier amount function lockMultiplier(uint256 secs) public view returns (uint256) { return Math.min( lock_max_multiplier, (secs * lock_max_multiplier) / lock_time_for_max_multiplier ) ; } // ------ FRAX RELATED ------ /// @notice The amount of FRAX denominated value being boosted that an address has staked /// @param account The address to check /// @return The amount of FRAX value boosted function userStakedFrax(address account) public view returns (uint256) { return (fraxPerLPStored * _locked_liquidity[account]) / MULTIPLIER_PRECISION; } /// @notice The amount of FRAX denominated value being boosted that a proxy address has staked /// @param proxy_address The address to check /// @return The amount of FRAX value boosted function proxyStakedFrax(address proxy_address) public view returns (uint256) { return (fraxPerLPStored * proxy_lp_balances[proxy_address]) / MULTIPLIER_PRECISION; } /// @notice The maximum LP that can get max veFXS boosted for a given address at its current veFXS balance /// @param account The address to check /// @return The maximum 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); } /// @notice Must be overriden to return the current FRAX per LP token /// @return The current number of FRAX per LP token function fraxPerLPToken() public virtual view returns (uint256) { revert("Need fPLPT logic"); } // ------ veFXS RELATED ------ /// @notice The minimum veFXS required to get max boost for a given address /// @param account The address to check /// @return The minimum veFXS required to get max boost function minVeFXSForMaxBoost(address account) public view returns (uint256) { return (userStakedFrax(account) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } /// @notice The minimum veFXS required to get max boost for a given proxy /// @param proxy_address The proxy address /// @return The minimum veFXS required to get max boost function minVeFXSForMaxBoostProxy(address proxy_address) public view returns (uint256) { return (proxyStakedFrax(proxy_address) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } /// @notice Looks up a staker's proxy /// @param addr The address to check /// @return the_proxy The proxy address, or address(0) 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]; } } /// @notice The multiplier for a given account, based on veFXS /// @param account The account to check /// @return vefxs_multiplier The multiplier boost for the account 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 =============== */ /// @notice Toggle whether a staker can use the proxy's veFXS balance to boost yields /// @notice Proxy must call this first, then the staker must call stakerSetVeFXSProxy 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]; } } /// @notice After proxy toggles staker to true, staker must call and confirm this /// @param proxy_address The address of the veFXS proxy 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) internal { _updateRewardAndBalance(account, sync_too, false); } function _updateRewardAndBalance(address account, bool sync_too, bool pre_sync_vemxstored) internal { // Skip certain functions if we are in an emergency shutdown if (!withdrawalOnlyShutdown) { // Need to retro-adjust some things if the period hasn't been renewed, then start a new one if (sync_too){ sync(); } } // Used to make sure the veFXS multiplier is correct if a stake is increased, before calcCurCombinedWeight if (pre_sync_vemxstored){ _vefxsMultiplierStored[account] = veFXSMultiplier(account); } 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 if (!withdrawalOnlyShutdown) _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 ------ /// @notice A function that can be overridden to add extra logic to the getReward function /// @param destination_address The address to send the rewards to function getRewardExtraLogic(address destination_address) public nonReentrant { require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); 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 /// @notice Claims rewards to destination address /// @param destination_address The address to send the rewards to /// @return rewards_before The rewards available before the claim function getReward(address destination_address) external nonReentrant returns (uint256[] memory) { return _getReward(msg.sender, destination_address, true); } /// @notice Claims rewards to destination address & wether to do extra logic /// @param destination_address The address to send the rewards to /// @param claim_extra_too Whether to do extra logic /// @return rewards_before The rewards available before the claim 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) { // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Make sure rewards collection isn't paused require(rewardsCollectionPaused == false, "Rewards collection paused"); // Update the last reward claim time first, as an extra reentrancy safeguard lastRewardClaimTime[rewardee] = block.timestamp; // 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 { // Catch up the old rewards first _updateStoredRewardsAndTime(); // 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); // Aura & Balancer Gauge Rewards // ========================================== // 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 // Should only be called once per week max // if (rewardRatesManual[1] != 0) { // // AURA & BAL // // ==================================== // uint256 aura_before = IERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 bal_before = IERC20(rewardTokens[2]).balanceOf(address(this)); // aura_deposit_vault.getReward(address(this), true); // uint256 aura_after = IERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 bal_after = IERC20(rewardTokens[2]).balanceOf(address(this)); // // Set the new reward rates // rewardRatesManual[1] = (aura_after - aura_before) / rewardsDuration; // AURA // rewardRatesManual[2] = (bal_after - bal_before) / rewardsDuration; // BAL // } // Bunni oLIT rewards // ========================================== // 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 // Should only be called once per week max // if (rewardRatesManual[1] != 0) { // // oLIT // // ==================================== // uint256 olit_before = IERC20(rewardTokens[1]).balanceOf(address(this)); // minter.mint(address(stakingToken)); // uint256 olit_after = IERC20(rewardTokens[1]).balanceOf(address(this)); // // Set the new reward rate // rewardRatesManual[1] = (olit_after - olit_before) / rewardsDuration; // } // CONVEX EXTRA REWARDS (OLD METHOD) // ========================================== // 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; // } // Make sure everything is caught up again _updateStoredRewardsAndTime(); } 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(); } /// @notice Updates the gauge weights, if applicable /// @param force_update If true, will update the weights even if the time hasn't elapsed 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(); } } } } /// @notice Updates gauge weights, fraxPerLP, pulls in new rewards or updates rewards function sync() public { // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // 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 ------ /// @notice Owner or governance can pause/unpause staking, withdrawals, rewards collection, and collectRewardsOnWithdrawal /// @param _stakingPaused Whether staking is paused /// @param _withdrawalsPaused Whether withdrawals are paused /// @param _rewardsCollectionPaused Whether rewards collection is paused /// @param _withdrawalOnlyShutdown Whether you can only withdraw. Only settable once function setPauses( bool _stakingPaused, bool _withdrawalsPaused, bool _rewardsCollectionPaused, bool _withdrawalOnlyShutdown ) external onlyByOwnGov { stakingPaused = _stakingPaused; withdrawalsPaused = _withdrawalsPaused; rewardsCollectionPaused = _rewardsCollectionPaused; // Only settable once. Rewards math will be permanently wrong afterwards, so only use // for recovering LP if(_withdrawalOnlyShutdown && !withdrawalOnlyShutdown) withdrawalOnlyShutdown = true; } /* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */ /// @notice Owner or governance can unlock stakes - irreversible! function unlockStakes() external onlyByOwnGov { stakesUnlocked = !stakesUnlocked; } /// @notice Owner or governance sets whether an address is a valid veFXS proxy /// @param _proxy_addr The address to set function toggleValidVeFXSProxy(address _proxy_addr) external onlyByOwnGov { valid_vefxs_proxies[_proxy_addr] = !valid_vefxs_proxies[_proxy_addr]; } /// @notice Allows owner to recover any ERC20 or token manager to recover their reward token. /// @param tokenAddress The address of the token to recover /// @param tokenAmount The amount of the token to recover function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) { // Check if the desired token is a reward token bool isRewTkn = isRewardToken[tokenAddress]; // 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 ( (isRewTkn && rewardManagers[tokenAddress] == msg.sender) || (!isRewTkn && (msg.sender == owner)) ) { // // Aura & Balancer // // Withdraw the tokens from the Aura vault. Do not claim // // ========================================= // if (tokenAddress == address(stakingToken)) aura_deposit_vault.withdraw(tokenAmount, false); TransferHelper.safeTransfer(tokenAddress, msg.sender, tokenAmount); return; } // If none of the above conditions are true else { revert("No valid tokens to recover"); } } /// @notice Sets multiple variables at once /// @param _misc_vars The variables to set: /// [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 /// [6] uint256 _max_stake_limit (must be at greater or equal to old value) 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 /// @notice Allows owner or reward token managers to set the reward rate for a given reward token /// @param reward_token_address The address of the reward token /// @param _new_rate The new reward rate (token amount divided by reward period duration) /// @param _gauge_controller_address The address of the gauge controller for this reward token /// @param _rewards_distributor_address The address of the rewards distributor for this reward token 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 /// @notice Allows owner or reward token managers to change the reward manager for a given reward token /// @param reward_token_address The address of the reward token /// @param new_manager_address The new reward manager address 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/Staking/FraxUnifiedFarm_ERC20.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================= FraxUnifiedFarm_ERC20 ====================== // ==================================================================== // For ERC20 Tokens // Uses FraxUnifiedFarmTemplate.sol // -------------------- VARIES -------------------- // Balancer // import "../Misc_AMOs/balancer/IBalancerGauge.sol"; // Bunni // import "../Misc_AMOs/bunni/IBunniGauge.sol"; // Convex wrappers // import "../Curve/ICurvefrxETHETHPool.sol"; // import "../Misc_AMOs/convex/IDepositToken.sol"; // import "../Misc_AMOs/curve/I2poolTokenNoLending.sol"; // import "../Misc_AMOs/curve/ICurveStableSwapNG.sol"; // import "../Misc_AMOs/curve/ICurveStableSwapMetaNG.sol"; // import "../Misc_AMOs/curve/ICurveTricryptoOptimizedWETH.sol"; // Convex FXB // import "../Misc_AMOs/curve/ICurveStableSwapNG.sol"; // import '../FXB/IFXB.sol'; // Fraxlend // import '../Fraxlend/IFraxlendPair.sol'; // Fraxswap // import '../Fraxswap/core/interfaces/IFraxswapPair.sol'; // G-UNI // import "../Misc_AMOs/gelato/IGUniPool.sol"; // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // import "../Misc_AMOs/kyberswap/elastic/IKyberSwapFarmingToken.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 -------------------- // Bunni // Declared in FraxUnifiedFarmTemplate.sol // Balancer // Declared in FraxUnifiedFarmTemplate.sol // Convex crvUSD/FRAX IConvexStakingWrapperFrax public stakingToken; // I2poolTokenNoLending public curveToken; // ICurvefrxETHETHPool public curvePool; // Convex stkcvxFPIFRAX, stkcvxFRAXBP, etc // IConvexStakingWrapperFrax public stakingToken; I2poolToken public curveToken; // ICurveStableSwapNG public curveToken; // ICurveStableSwapMetaNG public curveToken; // ICurveTricryptoOptimizedWETH public curveToken; I2pool public curvePool; // ICurvefrxETHETHPool public curvePool; // ICurveStableSwapNG public curvePool; // ICurveStableSwapMetaNG public curvePool; // ICurveTricryptoOptimizedWETH public curvePool; // Fraxswap // IFraxswapPair public stakingToken; // Fraxlend // IFraxlendPair public stakingToken; // G-UNI // IGUniPool public stakingToken; // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // IKyberSwapFarmingToken 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) -------------------- // Bunni // USE CHILD // Convex stkcvxFPIFRAX, stkcvxFRAXBP, etc // USE CHILD // Fraxlend // USE CHILD // Fraxswap // USE CHILD // G-UNI // stakingToken = IGUniPool(_stakingToken); // address token0 = address(stakingToken.token0()); // frax_is_token0 = (token0 == frax_address); // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // stakingToken = IKyberSwapFarmingToken(_stakingToken); // 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; // Balancer // ============================================ // USE CHILD // Bunni // ============================================ // USE CHILD // Convex stkcvxFPIFRAX and stkcvxFRAXBP only // ============================================ // USE CHILD // Convex Stable/FRAXBP // ============================================ // USE CHILD // Convex Volatile/FRAXBP // ============================================ // USE CHILD // Fraxlend // ============================================ // USE CHILD // Fraxswap // ============================================ // USE CHILD // 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(); // } // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // ============================================ // USE CHILD // 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 _updateLiqAmts(address staker_address, uint256 amt, bool is_add) internal { // Get the proxy address address the_proxy = getProxyFor(staker_address); if (is_add) { // Update total liquidities _total_liquidity_locked += amt; _locked_liquidity[staker_address] += amt; // Update the proxy if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += amt; } else { // Update total liquidities _total_liquidity_locked -= amt; _locked_liquidity[staker_address] -= amt; // Update the proxy if (the_proxy != address(0)) proxy_lp_balances[the_proxy] -= amt; } // Need to call to update the combined weights _updateRewardAndBalance(staker_address, false, true); } function _getStake(address staker_address, bytes32 kek_id) internal view returns (LockedStake memory locked_stake, uint256 arr_idx) { if (kek_id != 0) { 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(kek_id != 0 && 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 public { // Make sure staking isn't paused require(!stakingPaused, "Staking paused"); // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Claim rewards at the old balance first _getReward(msg.sender, msg.sender, true); // 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); // // Aura & Balancer // // Deposit the tokens into the Aura vault // // ========================================= // stakingToken.approve(address(aura_deposit_vault), addl_liq); // aura_deposit_vault.stake(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 _updateLiqAmts(msg.sender, addl_liq, true); 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 public { // Make sure staking isn't paused require(!stakingPaused, "Staking paused"); // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Claim rewards at the old balance first _getReward(msg.sender, msg.sender, true); // 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, true); 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(!withdrawalOnlyShutdown, "Only withdrawals allowed"); require(!stakingPaused, "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); // // Aura & Balancer // // Deposit the tokens into the Aura vault // // ========================================= // stakingToken.approve(address(aura_deposit_vault), liquidity); // aura_deposit_vault.stake(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 _updateLiqAmts(staker_address, liquidity, true); emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address); return kek_id; } // ------ WITHDRAWING ------ /// @notice Withdraw a stake. /// @param kek_id The id for the stake /// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless) /// @dev Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues (important for migration) function withdrawLocked(bytes32 kek_id, address destination_address, bool claim_rewards_deprecated) nonReentrant external returns (uint256) { require(withdrawalsPaused == false, "Withdrawals paused"); return _withdrawLocked(msg.sender, destination_address, kek_id, claim_rewards_deprecated); } /// @notice No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper functions like withdraw(), migrator_withdraw_unlocked() and migrator_withdraw_locked() /// @param staker_address The address of the staker /// @param destination_address Destination address for the withdrawn LP /// @param kek_id The id for the stake /// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless) function _withdrawLocked( address staker_address, address destination_address, bytes32 kek_id, bool claim_rewards_deprecated ) internal returns (uint256) { // Collect rewards first and then update the balances // withdrawalOnlyShutdown to be used in an emergency situation if reward is overemitted or not available // and the user can forfeit rewards to get their principal back. if (withdrawalOnlyShutdown) { // Do nothing. } else { // Get the reward _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) { // // Aura & Balancer // // Withdraw the tokens from the Aura vault. Do not claim // // ========================================= // aura_deposit_vault.withdraw(liquidity, false); // Give the tokens to the destination_address // Should throw if insufficient balance TransferHelper.safeTransfer(address(stakingToken), destination_address, liquidity); // Remove the stake from the array delete lockedStakes[staker_address][theArrayIndex]; // Update liquidities _updateLiqAmts(staker_address, liquidity, 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/Misc_AMOs/convex/IDepositToken.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later 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/Staking/Variants/FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later contract FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile is FraxUnifiedFarm_ERC20 { string public farm_type = "ERC20_Convex_FRAXBP_Volatile"; 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) { // COMMENTED OUT SO COMPILER DOESNT COMPLAIN. UNCOMMENT WHEN DEPLOYING // Convex stkcvxFPIFRAX and stkcvxFRAXBP. Also Volatile/FRAXBP stakingToken = IConvexStakingWrapperFrax(_stakingToken); curveToken = I2poolToken(stakingToken.curveToken()); curvePool = I2pool(curveToken.minter()); address token0 = curvePool.coins(0); frax_is_token0 = (token0 == frax_address); } function fraxPerLPToken() public view override returns (uint256 frax_per_lp_token) { // COMMENTED OUT SO COMPILER DOESNT COMPLAIN. UNCOMMENT WHEN DEPLOYING // 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() * (1e18)) / (4 * curvePool.price_oracle()); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"internalType":"address[]","name":"_rewardManagers","type":"address[]"},{"internalType":"uint256[]","name":"_rewardRates","type":"uint256[]"},{"internalType":"address[]","name":"_gaugeControllers","type":"address[]"},{"internalType":"address[]","name":"_rewardDistributors","type":"address[]"},{"internalType":"address","name":"_stakingToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedAdditional","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"new_secs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_start_ts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_end_ts","type":"uint256"}],"name":"LockedLonger","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token_address","type":"address"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secs","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"source_address","type":"address"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"WithdrawLocked","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"calcCurCombinedWeight","outputs":[{"internalType":"uint256","name":"old_combined_weight","type":"uint256"},{"internalType":"uint256","name":"new_vefxs_multiplier","type":"uint256"},{"internalType":"uint256","name":"new_combined_weight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"stake_idx","type":"uint256"}],"name":"calcCurrLockMultiplier","outputs":[{"internalType":"uint256","name":"midpoint_lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"address","name":"new_manager_address","type":"address"}],"name":"changeTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"combinedWeightOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"contract I2pool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveToken","outputs":[{"internalType":"contract I2poolToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"new_earned","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"farm_type","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPToken","outputs":[{"internalType":"uint256","name":"frax_per_lp_token","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getProxyFor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getReward","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_extra_too","type":"bool"}],"name":"getReward2","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getRewardExtraLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256[]","name":"rewards_per_duration_arr","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller_addr","type":"address"},{"internalType":"address","name":"reward_token_addr","type":"address"}],"name":"isTokenManagerFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRewardClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"addl_liq","type":"uint256"}],"name":"lockAdditional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"new_ending_ts","type":"uint256"}],"name":"lockLonger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"lockMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_for_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedLiquidityOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedStakes","outputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOf","outputs":[{"components":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"internalType":"struct FraxUnifiedFarm_ERC20.LockedStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOfLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"maxLPForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"minVeFXSForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"minVeFXSForMaxBoostProxy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"proxyStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"}],"name":"proxyToggleStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxy_lp_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token_idx","type":"uint256"}],"name":"rewardRates","outputs":[{"internalType":"uint256","name":"rwd_rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint256[]","name":"newRewardsPerTokenStored","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[6]","name":"_misc_vars","type":"uint256[6]"}],"name":"setMiscVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalsPaused","type":"bool"},{"internalType":"bool","name":"_rewardsCollectionPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalOnlyShutdown","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"}],"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":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_rewards_deprecated","type":"bool"}],"name":"withdrawLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalOnlyShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
671bc16d674ec8000060068190556305a39a806007556001600855673782dace9d9000006009819055600a91909155600b5560c06040526005608090815264189718171b60d91b60a05260239062000058908262000781565b5060408051808201909152601c81527f45524332305f436f6e7665785f4652415842505f566f6c6174696c650000000060208201526028906200009c908262000781565b50348015620000aa57600080fd5b5060405162005f3438038062005f34833981016040819052620000cd91620009a9565b86868686868686868686868686856001600160a01b038116620001365760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15060016002558451620001a89060109060208801906200061b565b508151620001be9060119060208501906200061b565b508051620001d49060129060208401906200061b565b508251620001ea90601390602086019062000685565b5060005b85518110156200039e57806015600088848151811062000212576200021262000ab0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555060016014600088848151811062000259576200025962000ab0565b6020908102919091018101516001600160a01b031682528101919091526040016000908120805460ff191692151592909217909155601680546001810182559082527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901558451859082908110620002d557620002d562000ab0565b6020026020010151600f6000888481518110620002f657620002f662000ab0565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601a805460018181019092557f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01829055601b805480830182559083527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc1019190915501620001ee565b506022805460ff19169055426005556040805163513872bd60e01b81529051733669c421b77340b2979d1a00a792cc2ee0fce7379163513872bd9160048083019260209291908290030181865afa158015620003fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000424919062000ac6565b6004819055505050505050505050505050505080602460016101000a8154816001600160a01b0302191690836001600160a01b03160217905550602460019054906101000a90046001600160a01b03166001600160a01b0316634f39059c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004d8919062000ae0565b602580546001600160a01b0319166001600160a01b03929092169182179055604080516303aa30b960e11b815290516307546172916004808201926020929091908290030181865afa15801562000533573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000559919062000ae0565b602680546001600160a01b0319166001600160a01b0392909216918217905560405163c661065760e01b8152600060048201819052919063c661065790602401602060405180830381865afa158015620005b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005dd919062000ae0565b6024805460ff19166001600160a01b0390921673853d955acef822db058eb8505911ed77f175b99e149190911790555062000b059650505050505050565b82805482825590600052602060002090810192821562000673579160200282015b828111156200067357825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200063c565b5062000681929150620006c3565b5090565b82805482825590600052602060002090810192821562000673579160200282015b8281111562000673578251825591602001919060010190620006a6565b5b80821115620006815760008155600101620006c4565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200070557607f821691505b6020821081036200072657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200077c576000816000526020600020601f850160051c81016020861015620007575750805b601f850160051c820191505b81811015620007785782815560010162000763565b5050505b505050565b81516001600160401b038111156200079d576200079d620006da565b620007b581620007ae8454620006f0565b846200072c565b602080601f831160018114620007ed5760008415620007d45750858301515b600019600386901b1c1916600185901b17855562000778565b600085815260208120601f198616915b828110156200081e57888601518255948401946001909101908401620007fd565b50858210156200083d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200086557600080fd5b919050565b604051601f8201601f191681016001600160401b0381118282101715620008955762000895620006da565b604052919050565b60006001600160401b03821115620008b957620008b9620006da565b5060051b60200190565b600082601f830112620008d557600080fd5b81516020620008ee620008e8836200089d565b6200086a565b8083825260208201915060208460051b8701019350868411156200091157600080fd5b602086015b8481101562000938576200092a816200084d565b835291830191830162000916565b509695505050505050565b600082601f8301126200095557600080fd5b8151602062000968620008e8836200089d565b8083825260208201915060208460051b8701019350868411156200098b57600080fd5b602086015b8481101562000938578051835291830191830162000990565b600080600080600080600060e0888a031215620009c557600080fd5b620009d0886200084d565b60208901519097506001600160401b0380821115620009ee57600080fd5b620009fc8b838c01620008c3565b975060408a015191508082111562000a1357600080fd5b62000a218b838c01620008c3565b965060608a015191508082111562000a3857600080fd5b62000a468b838c0162000943565b955060808a015191508082111562000a5d57600080fd5b62000a6b8b838c01620008c3565b945060a08a015191508082111562000a8257600080fd5b5062000a918a828b01620008c3565b92505062000aa260c089016200084d565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000ad957600080fd5b5051919050565b60006020828403121562000af357600080fd5b62000afe826200084d565b9392505050565b61541f8062000b156000396000f3fe608060405234801561001057600080fd5b506004361061043b5760003560e01c80637d6ef08e11610235578063d2010fb411610135578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a1e578063facefb6414610a31578063fff6cae914610a4457600080fd5b8063f2a8d34914610a02578063f2caeb1e14610a0b57600080fd5b8063e1ba95d2146109d5578063e7f30582146109dd578063ebe2b12b146109f0578063f288baf6146109f957600080fd5b8063d7400d5611610104578063d7400d5614610971578063d9f96e8d14610984578063de1a6551146109ba578063e01f62bf146109cd57600080fd5b8063d2010fb41461092f578063d2fbdc0d14610938578063d42fc9b41461094b578063d5e1a9c61461095e57600080fd5b8063a0f23476116101c8578063c00007b011610197578063c8f33c911161017c578063c8f33c91146108e7578063ca6df29d146108f0578063cdc82e801461092657600080fd5b8063c00007b0146108c1578063c3543826146108d457600080fd5b8063a0f2347614610889578063aa1d4fce1461089c578063b85efd06146108a5578063b94c4dcb146108b857600080fd5b80638bad86a7116102045780638bad86a71461081b5780638da5cb5b1461084957806391cf600a146108695780639637927f1461087c57600080fd5b80637d6ef08e146107c15780637f472e54146107e05780638980f11f146107f357806389b5f00b1461080657600080fd5b806341a16f3f1161034057806369339245116102d357806372f702f3116102a25780637910d17b116102875780637910d17b1461076b5780637970833e1461077e57806379ba5097146107b957600080fd5b806372f702f314610733578063774d4ae71461075857600080fd5b806369339245146106e25780636c430dbb146107025780636e27cef91461072257806370641a361461072b57600080fd5b806353a47bb71161030f57806353a47bb7146106aa57806354fd4d50146106ca5780635bfd9258146106d257806364f2c060146106da57600080fd5b806341a16f3f1461062c57806341edbdf0146106625780634f39059c146106775780634fd2b5361461069757600080fd5b80631face856116103d35780632c0c2a0a116103a257806336f89af21161038757806336f89af2146105d9578063386a95251461060f578063387edc861461061957600080fd5b80632c0c2a0a146105b35780632df079f1146105c657600080fd5b80631face85614610502578063218751b214610515578063231b68dc1461055a57806328408bab1461057d57600080fd5b80631627540c1161040f5780631627540c146104b257806317b18c89146104c75780631c1f78eb146104da5780631e090f01146104e257600080fd5b80628cc262146104405780630238b936146104695780630d7bac4f1461048a57806312edb24c1461049d575b600080fd5b61045361044e366004614e09565b610a4c565b6040516104609190614e24565b60405180910390f35b61047c610477366004614e76565b610bc1565b604051908152602001610460565b61047c610498366004614eb6565b610cc2565b6104a5610cee565b6040516104609190614ecf565b6104c56104c0366004614e09565b610d5d565b005b61047c6104d5366004614f1d565b610e7d565b610453610f07565b6104f56104f0366004614e09565b610f9e565b6040516104609190614f3f565b61047c610510366004614e09565b611052565b6026546105359073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610460565b61056d610568366004614fad565b611097565b6040519015158152602001610460565b61053561058b366004614e09565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6105c1366004614e09565b61117d565b6104c56105d4366004614fe0565b611469565b61047c6105e7366004614e09565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61047c62093a8081565b6104c5610627366004614e09565b6115e2565b61053561063a366004614e09565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61066a611741565b6040516104609190615060565b6025546105359073ffffffffffffffffffffffffffffffffffffffff1681565b61047c6106a5366004614e09565b6117cf565b6001546105359073ffffffffffffffffffffffffffffffffffffffff1681565b61066a6117f0565b61047c6117fd565b601d5461047c565b61047c6106f0366004614e09565b60156020526000908152604090205481565b61047c610710366004614e09565b60196020526000908152604090205481565b61047c60085481565b61045361194e565b60245461053590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6107663660046150b1565b611aa3565b6104536107793660046150db565b611caf565b61079161078c3660046150b1565b611d2b565b604080519586526020860194909452928401919091526060830152608082015260a001610460565b6104c5611d79565b61047c6107cf366004614e09565b602080526000908152604090205481565b61047c6107ee366004614e09565b611ec4565b6104c56108013660046150b1565b611edb565b60225461056d90640100000000900460ff1681565b61082e610829366004614e09565b61206c565b60408051938452602084019290925290820152606001610460565b6000546105359073ffffffffffffffffffffffffffffffffffffffff1681565b6104c5610877366004614e09565b612299565b60225461056d9060ff1681565b61047c610897366004614e09565b61238c565b61047c60095481565b6104c56108b3366004614f1d565b612456565b61047c60075481565b6104536108cf366004614e09565b6126f2565b6105356108e2366004614e09565b61277a565b61047c60055481565b61047c6108fe366004614e09565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b61047c60065481565b61047c60035481565b6104c5610946366004614f1d565b6127dd565b61047c610959366004614e09565b612c2a565b6104c561096c366004615112565b612c66565b6104c561097f366004614e09565b612e55565b61047c610992366004614e09565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104c56109c8366004614fad565b61306f565b601c5461047c565b6104c5613156565b6104c56109eb366004614e09565b613227565b61047c60045481565b61047c600a5481565b61047c600b5481565b61047c610a19366004614eb6565b613387565b6104c5610a2c36600461515f565b61349e565b6104c5610a3f3660046151ab565b61366a565b6104c561382a565b60606000610a5861194e565b60105490915067ffffffffffffffff811115610a7657610a7661517c565b604051908082528060200260200182016040528015610a9f578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610bbb5760005b601054811015610bb95773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610b3e57610b3e615250565b6020026020010151610b5091906152ae565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b8091906152c1565b610b8a91906152d8565b610b949190615313565b838281518110610ba657610ba6615250565b6020908102919091010152600101610ad1565b505b50919050565b60006002805403610c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610ca9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610c2a565b610cb5338486856138cf565b6001600255949350505050565b600654600754600091610ce891610cd982866152c1565b610ce391906152d8565b613a8e565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610d5357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d28575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610c2a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610eea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055610efb3380858542613aa6565b60016002559392505050565b60135460609067ffffffffffffffff811115610f2557610f2561517c565b604051908082528060200260200182016040528015610f4e578160200160208202803683370190505b50905060005b601354811015610f9a5762093a80610f6b82613387565b610f7591906152c1565b828281518110610f8757610f87615250565b6020908102919091010152600101610f54565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561104757838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610fe3565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a76400009161108d916152c1565b610ce891906152d8565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff166110cc57506000610ce8565b73ffffffffffffffffffffffffffffffffffffffff83161580611103575073ffffffffffffffffffffffffffffffffffffffff8216155b1561111057506000610ce8565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361113b57506001610ce8565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f602052604090205481851691160361117457506001610ce8565b50600092915050565b6000808061118a8461277a565b905073ffffffffffffffffffffffffffffffffffffffff81161561124f576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124a9190615326565b6112f1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156112cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f19190615326565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190615326565b61138b91906152c1565b600954600a5461139b90866152c1565b6113a591906152c1565b6113af91906152d8565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156113de576113d984611ec4565b6113e7565b6113e7876117cf565b9050801561143957600081611404670de0b6b3a7640000886152c1565b61140e91906152d8565b9050670de0b6b3a7640000600a548261142791906152c1565b61143191906152d8565b92505061143e565b600091505b5080821161144c578061144e565b815b9450600a5485111561146057600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114a25750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115a75750602254640100000000900460ff16155b156115dc57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b600280540361164d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055602254640100000000900460ff16156116c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b60225462010000900460ff1615611739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c2a565b506001600255565b6028805461174e9061533f565b80601f016020809104026020016040519081016040528092919081815260200182805461177a9061533f565b80156117c75780601f1061179c576101008083540402835291602001916117c7565b820191906000526020600020905b8154815290600101906020018083116117aa57829003601f168201915b505050505081565b6000670de0b6b3a7640000600b546117e684612c2a565b61108d91906152c1565b6023805461174e9061533f565b602654604080517f86fc88d3000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916386fc88d39160048083019260209291908290030181865afa15801561186d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118919190615326565b61189c9060046152c1565b602660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354f0f7d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192d9190615326565b61193f90670de0b6b3a76400006152c1565b61194991906152d8565b905090565b6060601c54600014806119615750601d54155b156119bb576016805480602002602001604051908101604052809291908181526020018280548015610d5357602002820191906000526020600020905b81548152602001906001019080831161199e575050505050905090565b60105467ffffffffffffffff8111156119d6576119d661517c565b6040519080825280602002602001820160405280156119ff578160200160208202803683370190505b50905060005b601654811015610f9a57601d54611a1b82613387565b600554611a26613e6a565b611a3091906152ae565b611a3a91906152c1565b611a4c90670de0b6b3a76400006152c1565b611a5691906152d8565b60168281548110611a6957611a69615250565b9060005260206000200154611a7e9190615313565b828281518110611a9057611a90615250565b6020908102919091010152600101611a05565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611add57611add615250565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611b5b57506020810151611b83565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611c4357606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611c3a576000818360600151611bd191906152ae565b90506000836060015142611be591906152ae565b90506000611bf76104986002856152d8565b90506000611c0583826152c1565b611c0f85846152c1565b611c199190615313565b9050611c258385615313565b611c2f90826152d8565b965050505050611c93565b60009250611c93565b600080828460600151611c5691906152ae565b90506000428560600151611c6a91906152ae565b90506002611c788284615313565b611c8291906152d8565b92505050611c8f81610cc2565b9350505b8160800151831115611ca757816080015192505b505092915050565b60606002805403611d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055610efb338484613e78565b60276020528160005260406000208181548110611d4757600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610c2a565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b546117e684611052565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611f085750611f083382611097565b611f6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff16808015611fca575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ff5575080158015611ff5575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15612005576115dc8433856141b1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610c2a565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054908061209d8461117d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040812054919350901580156120f7575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b80612127575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15612133575081612173565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020546002906121669085615313565b61217091906152d8565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156122905773ffffffffffffffffffffffffffffffffffffffff861660009081526027602052604081208054839081106121de576121de615250565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006122378884611aa3565b60408301519091506000670de0b6b3a76400006122548785615313565b61225e90846152c1565b61226891906152d8565b6122729083615313565b905061227e8188615313565b9650506001909301925061217a915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122d25750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461239e91906152c1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244c9190615326565b6117e691906152c1565b60028054036124c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b600280556022546301000000900460ff1615612539576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b602254640100000000900460ff16156125ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6125ba33336001613e78565b506000806125c83385614321565b9150915060008383604001516125de9190615313565b905060245461260a90610100900473ffffffffffffffffffffffffffffffffffffffff163330876144ef565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260279091529190912080548490811061265c5761265c615250565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506126ab3385600161468d565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6060600280540361275f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b6002805561276f33836001613e78565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff16156127ac575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b600280556022546301000000900460ff16156128c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b602254640100000000900460ff1615612935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b61294133336001613e78565b5060008061294f3385614321565b915091504283116129bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610c2a565b6000428360600151116129d05760006129e0565b4283606001516129e091906152ae565b905060006129ee42866152ae565b9050818111612a59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610c2a565b600854811015612ac5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c2a565b600754811115612b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c2a565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612b6183610cc2565b9052336000908152602760205260409020805485908110612b8457612b84615250565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612bd433600060016147fc565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a76400009161108d916152c1565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612c935750612c933382611097565b612cf9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054601380548692908110612d3457612d34615250565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612d9557612d95615250565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260159091526040902054601280548492908110612e0657612e06615250565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612f7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610c2a565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ff257336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff851684529180528220805491929091612fec9084906152ae565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091613066908490615313565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061309c575061309c3382611097565b613102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061318f5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6131f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff166132a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c2a565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036133845773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161337e9084906152ae565b90915550505b50565b6000806011838154811061339d5761339d615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561347857670de0b6b3a7640000601a84815481106133e3576133e3615250565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345d9190615326565b61346791906152c1565b61347191906152d8565b9150610bbb565b6013838154811061348b5761348b615250565b9060005260206000200154915050919050565b60005b601154811015613666576000601182815481106134c0576134c0615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561365d5782806135125750601b828154811061350457613504615250565b906000526020600020015442115b1561365d576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ad9190615326565b601a83815481106135c0576135c0615250565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061363d9190615326565b601b838154811061365057613650615250565b6000918252602090912001555b506001016134a1565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806136a35750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b8051670de0b6b3a7640000111561377c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610c2a565b6080810151600111801590613796575060a0810151600111155b6137fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610c2a565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff161561389f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6138a9600061349e565b6138b16117fd565b60035560045442106138c7576138c561497b565b565b6138c5614c90565b602254600090640100000000900460ff166138f2576138f085856001613e78565b505b6000806138ff8786614321565b9150915081606001514210158061391d575060225460ff1615156001145b613983576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610c2a565b60408201518015613a83576024546139b790610100900473ffffffffffffffffffffffffffffffffffffffff1688836141b1565b73ffffffffffffffffffffffffffffffffffffffff881660009081526027602052604090208054839081106139ee576139ee615250565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613a28908990839061468d565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b6000818310613a9d5781613a9f565b825b9392505050565b6000856001613ab7828260006147fc565b602254640100000000900460ff1615613b2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6022546301000000900460ff1615613ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b600854851015613c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c2a565b600754851115613c78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c2a565b602454613ca290610100900473ffffffffffffffffffffffffffffffffffffffff168830896144ef565b6000613cad86610cc2565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b90529092509060608101613da08a8a615313565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613dfc908b908a9061468d565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b600061194942600454613a8e565b6060836001613e89828260006147fc565b602254640100000000900460ff1615613efe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b60225462010000900460ff1615613f71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff811115613fb457613fb461517c565b604051908082528060200260200182016040528015613fdd578160200160208202803683370190505b50925060005b6010548110156141a75773ffffffffffffffffffffffffffffffffffffffff87166000908152601860209081526040808320848452909152902054845185908390811061403257614032615250565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff88166000908152601882526040808220848352909252908120819055845185908390811061408657614086615250565b6020026020010151111561419f576140f5601082815481106140aa576140aa615250565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16878684815181106140e8576140e8615250565b60200260200101516141b1565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061413f5761413f615250565b60200260200101516010848154811061415a5761415a615250565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101613fe3565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614248919061538c565b6000604051808303816000865af19150503d8060008114614285576040519150601f19603f3d011682016040523d82523d6000602084013e61428a565b606091505b50915091508180156142b45750805115806142b45750808060200190518101906142b491906153a8565b61431a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610c2a565b5050505050565b6143566040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156144735760005b73ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020548110156144715773ffffffffffffffffffffffffffffffffffffffff851660009081526027602052604090208054829081106143c5576143c5615250565b90600052602060002090600502016000015484036144695773ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902080548290811061441457614414615250565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614471565b600101614361565b505b82158015906144825750815183145b6144e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610c2a565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161458e919061538c565b6000604051808303816000865af19150503d80600081146145cb576040519150601f19603f3d011682016040523d82523d6000602084013e6145d0565b606091505b50915091508180156145fa5750805115806145fa5750808060200190518101906145fa91906153a8565b614685576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610c2a565b505050505050565b60006146988461277a565b9050811561474c5782601c60008282546146b29190615313565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906146ec908490615313565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156147475773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614741908490615313565b90915550505b6147f3565b82601c600082825461475e91906152ae565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906147989084906152ae565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156147f35773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548592906147ed9084906152ae565b90915550505b6115dc84600060015b602254640100000000900460ff1661481c57811561481c5761481c61382a565b80156148525761482b8361117d565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff83161561206757600080600061487c8661206c565b6022549295509093509150640100000000900460ff1661489f5761489f86614cf9565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c602052604090208290558281106149235760006148da84836152ae565b905080601d546148ea9190615313565b601d556148f78185615313565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550614685565b600061492f82856152ae565b905080601d5461493f91906152ae565b601d5561494c81856152ae565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614983614c90565b60005b601254811015614a6a576000601282815481106149a5576149a5615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614a61576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a5e91906153c5565b50505b50600101614986565b50600062093a8060045442614a7f91906152ae565b614a8991906152d8565b905060005b601054811015614c625760108181548110614aab57614aab615250565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614b22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b469190615326565b614b51836001615313565b62093a80614b5e84613387565b614b6891906152c1565b614b7291906152c1565b111560108281548110614b8757614b87615250565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614c59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2a9190615060565b50600101614a8e565b5062093a80614c72826001615313565b614c7c91906152c1565b600454614c899190615313565b6004556133845b6000614c9a61194e565b905060005b601654811015614cea57818181518110614cbb57614cbb615250565b602002602001015160168281548110614cd657614cd6615250565b600091825260209091200155600101614c9f565b50614cf3613e6a565b60055550565b73ffffffffffffffffffffffffffffffffffffffff811615613384576000614d2082610a4c565b905060005b8151811015614d8457818181518110614d4057614d40615250565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101614d25565b5060005b81518110156120675760168181548110614da457614da4615250565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff86168352601782526040808420858552909252912055600101614d88565b803573ffffffffffffffffffffffffffffffffffffffff811681146127d857600080fd5b600060208284031215614e1b57600080fd5b613a9f82614de5565b6020808252825182820181905260009190848201906040850190845b81811015614e5c57835183529284019291840191600101614e40565b50909695505050505050565b801515811461338457600080fd5b600080600060608486031215614e8b57600080fd5b83359250614e9b60208501614de5565b91506040840135614eab81614e68565b809150509250925092565b600060208284031215614ec857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614e5c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614eeb565b60008060408385031215614f3057600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614fa05781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614f5c565b5091979650505050505050565b60008060408385031215614fc057600080fd5b614fc983614de5565b9150614fd760208401614de5565b90509250929050565b60008060008060808587031215614ff657600080fd5b843561500181614e68565b9350602085013561501181614e68565b9250604085013561502181614e68565b9150606085013561503181614e68565b939692955090935050565b60005b8381101561505757818101518382015260200161503f565b50506000910152565b602081526000825180602084015261507f81604085016020870161503c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156150c457600080fd5b6150cd83614de5565b946020939093013593505050565b600080604083850312156150ee57600080fd5b6150f783614de5565b9150602083013561510781614e68565b809150509250929050565b6000806000806080858703121561512857600080fd5b61513185614de5565b93506020850135925061514660408601614de5565b915061515460608601614de5565b905092959194509250565b60006020828403121561517157600080fd5b8135613a9f81614e68565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c082840312156151bd57600080fd5b82601f8301126151cc57600080fd5b60405160c0810181811067ffffffffffffffff82111715615216577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561522b57600080fd5b845b8181101561524557803583526020928301920161522d565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610ce857610ce861527f565b8082028115828204841417610ce857610ce861527f565b60008261530e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610ce857610ce861527f565b60006020828403121561533857600080fd5b5051919050565b600181811c9082168061535357607f821691505b602082108103610bbb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000825161539e81846020870161503c565b9190910192915050565b6000602082840312156153ba57600080fd5b8151613a9f81614e68565b600080604083850312156153d857600080fd5b50508051602090910151909290915056fea264697066735822122004376bfec6e2db1dffd677da8ca0af68ab52621d1a5167a1ec4919820cf5b38364736f6c63430008170033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000007b465174a93a6d0602fd4ea99eec86c07e5e156800000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061043b5760003560e01c80637d6ef08e11610235578063d2010fb411610135578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a1e578063facefb6414610a31578063fff6cae914610a4457600080fd5b8063f2a8d34914610a02578063f2caeb1e14610a0b57600080fd5b8063e1ba95d2146109d5578063e7f30582146109dd578063ebe2b12b146109f0578063f288baf6146109f957600080fd5b8063d7400d5611610104578063d7400d5614610971578063d9f96e8d14610984578063de1a6551146109ba578063e01f62bf146109cd57600080fd5b8063d2010fb41461092f578063d2fbdc0d14610938578063d42fc9b41461094b578063d5e1a9c61461095e57600080fd5b8063a0f23476116101c8578063c00007b011610197578063c8f33c911161017c578063c8f33c91146108e7578063ca6df29d146108f0578063cdc82e801461092657600080fd5b8063c00007b0146108c1578063c3543826146108d457600080fd5b8063a0f2347614610889578063aa1d4fce1461089c578063b85efd06146108a5578063b94c4dcb146108b857600080fd5b80638bad86a7116102045780638bad86a71461081b5780638da5cb5b1461084957806391cf600a146108695780639637927f1461087c57600080fd5b80637d6ef08e146107c15780637f472e54146107e05780638980f11f146107f357806389b5f00b1461080657600080fd5b806341a16f3f1161034057806369339245116102d357806372f702f3116102a25780637910d17b116102875780637910d17b1461076b5780637970833e1461077e57806379ba5097146107b957600080fd5b806372f702f314610733578063774d4ae71461075857600080fd5b806369339245146106e25780636c430dbb146107025780636e27cef91461072257806370641a361461072b57600080fd5b806353a47bb71161030f57806353a47bb7146106aa57806354fd4d50146106ca5780635bfd9258146106d257806364f2c060146106da57600080fd5b806341a16f3f1461062c57806341edbdf0146106625780634f39059c146106775780634fd2b5361461069757600080fd5b80631face856116103d35780632c0c2a0a116103a257806336f89af21161038757806336f89af2146105d9578063386a95251461060f578063387edc861461061957600080fd5b80632c0c2a0a146105b35780632df079f1146105c657600080fd5b80631face85614610502578063218751b214610515578063231b68dc1461055a57806328408bab1461057d57600080fd5b80631627540c1161040f5780631627540c146104b257806317b18c89146104c75780631c1f78eb146104da5780631e090f01146104e257600080fd5b80628cc262146104405780630238b936146104695780630d7bac4f1461048a57806312edb24c1461049d575b600080fd5b61045361044e366004614e09565b610a4c565b6040516104609190614e24565b60405180910390f35b61047c610477366004614e76565b610bc1565b604051908152602001610460565b61047c610498366004614eb6565b610cc2565b6104a5610cee565b6040516104609190614ecf565b6104c56104c0366004614e09565b610d5d565b005b61047c6104d5366004614f1d565b610e7d565b610453610f07565b6104f56104f0366004614e09565b610f9e565b6040516104609190614f3f565b61047c610510366004614e09565b611052565b6026546105359073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610460565b61056d610568366004614fad565b611097565b6040519015158152602001610460565b61053561058b366004614e09565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6105c1366004614e09565b61117d565b6104c56105d4366004614fe0565b611469565b61047c6105e7366004614e09565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61047c62093a8081565b6104c5610627366004614e09565b6115e2565b61053561063a366004614e09565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61066a611741565b6040516104609190615060565b6025546105359073ffffffffffffffffffffffffffffffffffffffff1681565b61047c6106a5366004614e09565b6117cf565b6001546105359073ffffffffffffffffffffffffffffffffffffffff1681565b61066a6117f0565b61047c6117fd565b601d5461047c565b61047c6106f0366004614e09565b60156020526000908152604090205481565b61047c610710366004614e09565b60196020526000908152604090205481565b61047c60085481565b61045361194e565b60245461053590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b61047c6107663660046150b1565b611aa3565b6104536107793660046150db565b611caf565b61079161078c3660046150b1565b611d2b565b604080519586526020860194909452928401919091526060830152608082015260a001610460565b6104c5611d79565b61047c6107cf366004614e09565b602080526000908152604090205481565b61047c6107ee366004614e09565b611ec4565b6104c56108013660046150b1565b611edb565b60225461056d90640100000000900460ff1681565b61082e610829366004614e09565b61206c565b60408051938452602084019290925290820152606001610460565b6000546105359073ffffffffffffffffffffffffffffffffffffffff1681565b6104c5610877366004614e09565b612299565b60225461056d9060ff1681565b61047c610897366004614e09565b61238c565b61047c60095481565b6104c56108b3366004614f1d565b612456565b61047c60075481565b6104536108cf366004614e09565b6126f2565b6105356108e2366004614e09565b61277a565b61047c60055481565b61047c6108fe366004614e09565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b61047c60065481565b61047c60035481565b6104c5610946366004614f1d565b6127dd565b61047c610959366004614e09565b612c2a565b6104c561096c366004615112565b612c66565b6104c561097f366004614e09565b612e55565b61047c610992366004614e09565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104c56109c8366004614fad565b61306f565b601c5461047c565b6104c5613156565b6104c56109eb366004614e09565b613227565b61047c60045481565b61047c600a5481565b61047c600b5481565b61047c610a19366004614eb6565b613387565b6104c5610a2c36600461515f565b61349e565b6104c5610a3f3660046151ab565b61366a565b6104c561382a565b60606000610a5861194e565b60105490915067ffffffffffffffff811115610a7657610a7661517c565b604051908082528060200260200182016040528015610a9f578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610bbb5760005b601054811015610bb95773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610b3e57610b3e615250565b6020026020010151610b5091906152ae565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b8091906152c1565b610b8a91906152d8565b610b949190615313565b838281518110610ba657610ba6615250565b6020908102919091010152600101610ad1565b505b50919050565b60006002805403610c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610ca9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610c2a565b610cb5338486856138cf565b6001600255949350505050565b600654600754600091610ce891610cd982866152c1565b610ce391906152d8565b613a8e565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610d5357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d28575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610c2a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610eea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055610efb3380858542613aa6565b60016002559392505050565b60135460609067ffffffffffffffff811115610f2557610f2561517c565b604051908082528060200260200182016040528015610f4e578160200160208202803683370190505b50905060005b601354811015610f9a5762093a80610f6b82613387565b610f7591906152c1565b828281518110610f8757610f87615250565b6020908102919091010152600101610f54565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561104757838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610fe3565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a76400009161108d916152c1565b610ce891906152d8565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff166110cc57506000610ce8565b73ffffffffffffffffffffffffffffffffffffffff83161580611103575073ffffffffffffffffffffffffffffffffffffffff8216155b1561111057506000610ce8565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361113b57506001610ce8565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f602052604090205481851691160361117457506001610ce8565b50600092915050565b6000808061118a8461277a565b905073ffffffffffffffffffffffffffffffffffffffff81161561124f576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124a9190615326565b6112f1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156112cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f19190615326565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190615326565b61138b91906152c1565b600954600a5461139b90866152c1565b6113a591906152c1565b6113af91906152d8565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156113de576113d984611ec4565b6113e7565b6113e7876117cf565b9050801561143957600081611404670de0b6b3a7640000886152c1565b61140e91906152d8565b9050670de0b6b3a7640000600a548261142791906152c1565b61143191906152d8565b92505061143e565b600091505b5080821161144c578061144e565b815b9450600a5485111561146057600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114a25750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115a75750602254640100000000900460ff16155b156115dc57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b600280540361164d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055602254640100000000900460ff16156116c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b60225462010000900460ff1615611739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c2a565b506001600255565b6028805461174e9061533f565b80601f016020809104026020016040519081016040528092919081815260200182805461177a9061533f565b80156117c75780601f1061179c576101008083540402835291602001916117c7565b820191906000526020600020905b8154815290600101906020018083116117aa57829003601f168201915b505050505081565b6000670de0b6b3a7640000600b546117e684612c2a565b61108d91906152c1565b6023805461174e9061533f565b602654604080517f86fc88d3000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916386fc88d39160048083019260209291908290030181865afa15801561186d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118919190615326565b61189c9060046152c1565b602660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354f0f7d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192d9190615326565b61193f90670de0b6b3a76400006152c1565b61194991906152d8565b905090565b6060601c54600014806119615750601d54155b156119bb576016805480602002602001604051908101604052809291908181526020018280548015610d5357602002820191906000526020600020905b81548152602001906001019080831161199e575050505050905090565b60105467ffffffffffffffff8111156119d6576119d661517c565b6040519080825280602002602001820160405280156119ff578160200160208202803683370190505b50905060005b601654811015610f9a57601d54611a1b82613387565b600554611a26613e6a565b611a3091906152ae565b611a3a91906152c1565b611a4c90670de0b6b3a76400006152c1565b611a5691906152d8565b60168281548110611a6957611a69615250565b9060005260206000200154611a7e9190615313565b828281518110611a9057611a90615250565b6020908102919091010152600101611a05565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611add57611add615250565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611b5b57506020810151611b83565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611c4357606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611c3a576000818360600151611bd191906152ae565b90506000836060015142611be591906152ae565b90506000611bf76104986002856152d8565b90506000611c0583826152c1565b611c0f85846152c1565b611c199190615313565b9050611c258385615313565b611c2f90826152d8565b965050505050611c93565b60009250611c93565b600080828460600151611c5691906152ae565b90506000428560600151611c6a91906152ae565b90506002611c788284615313565b611c8291906152d8565b92505050611c8f81610cc2565b9350505b8160800151831115611ca757816080015192505b505092915050565b60606002805403611d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b60028055610efb338484613e78565b60276020528160005260406000208181548110611d4757600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610c2a565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b546117e684611052565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611f085750611f083382611097565b611f6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff16808015611fca575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ff5575080158015611ff5575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15612005576115dc8433856141b1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610c2a565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054908061209d8461117d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040812054919350901580156120f7575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b80612127575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15612133575081612173565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020546002906121669085615313565b61217091906152d8565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156122905773ffffffffffffffffffffffffffffffffffffffff861660009081526027602052604081208054839081106121de576121de615250565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006122378884611aa3565b60408301519091506000670de0b6b3a76400006122548785615313565b61225e90846152c1565b61226891906152d8565b6122729083615313565b905061227e8188615313565b9650506001909301925061217a915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122d25750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461239e91906152c1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244c9190615326565b6117e691906152c1565b60028054036124c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b600280556022546301000000900460ff1615612539576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b602254640100000000900460ff16156125ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6125ba33336001613e78565b506000806125c83385614321565b9150915060008383604001516125de9190615313565b905060245461260a90610100900473ffffffffffffffffffffffffffffffffffffffff163330876144ef565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260279091529190912080548490811061265c5761265c615250565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506126ab3385600161468d565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6060600280540361275f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b6002805561276f33836001613e78565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff16156127ac575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c2a565b600280556022546301000000900460ff16156128c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b602254640100000000900460ff1615612935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b61294133336001613e78565b5060008061294f3385614321565b915091504283116129bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610c2a565b6000428360600151116129d05760006129e0565b4283606001516129e091906152ae565b905060006129ee42866152ae565b9050818111612a59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610c2a565b600854811015612ac5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c2a565b600754811115612b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c2a565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612b6183610cc2565b9052336000908152602760205260409020805485908110612b8457612b84615250565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612bd433600060016147fc565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a76400009161108d916152c1565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612c935750612c933382611097565b612cf9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054601380548692908110612d3457612d34615250565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612d9557612d95615250565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260159091526040902054601280548492908110612e0657612e06615250565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612f7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610c2a565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ff257336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff851684529180528220805491929091612fec9084906152ae565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091613066908490615313565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061309c575061309c3382611097565b613102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c2a565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061318f5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6131f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff166132a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c2a565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036133845773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161337e9084906152ae565b90915550505b50565b6000806011838154811061339d5761339d615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561347857670de0b6b3a7640000601a84815481106133e3576133e3615250565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345d9190615326565b61346791906152c1565b61347191906152d8565b9150610bbb565b6013838154811061348b5761348b615250565b9060005260206000200154915050919050565b60005b601154811015613666576000601182815481106134c0576134c0615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561365d5782806135125750601b828154811061350457613504615250565b906000526020600020015442115b1561365d576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ad9190615326565b601a83815481106135c0576135c0615250565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061363d9190615326565b601b838154811061365057613650615250565b6000918252602090912001555b506001016134a1565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806136a35750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c2a565b8051670de0b6b3a7640000111561377c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610c2a565b6080810151600111801590613796575060a0810151600111155b6137fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610c2a565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff161561389f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6138a9600061349e565b6138b16117fd565b60035560045442106138c7576138c561497b565b565b6138c5614c90565b602254600090640100000000900460ff166138f2576138f085856001613e78565b505b6000806138ff8786614321565b9150915081606001514210158061391d575060225460ff1615156001145b613983576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610c2a565b60408201518015613a83576024546139b790610100900473ffffffffffffffffffffffffffffffffffffffff1688836141b1565b73ffffffffffffffffffffffffffffffffffffffff881660009081526027602052604090208054839081106139ee576139ee615250565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613a28908990839061468d565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b6000818310613a9d5781613a9f565b825b9392505050565b6000856001613ab7828260006147fc565b602254640100000000900460ff1615613b2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b6022546301000000900460ff1615613ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c2a565b600854851015613c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c2a565b600754851115613c78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c2a565b602454613ca290610100900473ffffffffffffffffffffffffffffffffffffffff168830896144ef565b6000613cad86610cc2565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b90529092509060608101613da08a8a615313565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613dfc908b908a9061468d565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b600061194942600454613a8e565b6060836001613e89828260006147fc565b602254640100000000900460ff1615613efe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c2a565b60225462010000900460ff1615613f71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c2a565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff811115613fb457613fb461517c565b604051908082528060200260200182016040528015613fdd578160200160208202803683370190505b50925060005b6010548110156141a75773ffffffffffffffffffffffffffffffffffffffff87166000908152601860209081526040808320848452909152902054845185908390811061403257614032615250565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff88166000908152601882526040808220848352909252908120819055845185908390811061408657614086615250565b6020026020010151111561419f576140f5601082815481106140aa576140aa615250565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16878684815181106140e8576140e8615250565b60200260200101516141b1565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061413f5761413f615250565b60200260200101516010848154811061415a5761415a615250565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101613fe3565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614248919061538c565b6000604051808303816000865af19150503d8060008114614285576040519150601f19603f3d011682016040523d82523d6000602084013e61428a565b606091505b50915091508180156142b45750805115806142b45750808060200190518101906142b491906153a8565b61431a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610c2a565b5050505050565b6143566040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156144735760005b73ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020548110156144715773ffffffffffffffffffffffffffffffffffffffff851660009081526027602052604090208054829081106143c5576143c5615250565b90600052602060002090600502016000015484036144695773ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902080548290811061441457614414615250565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614471565b600101614361565b505b82158015906144825750815183145b6144e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610c2a565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161458e919061538c565b6000604051808303816000865af19150503d80600081146145cb576040519150601f19603f3d011682016040523d82523d6000602084013e6145d0565b606091505b50915091508180156145fa5750805115806145fa5750808060200190518101906145fa91906153a8565b614685576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610c2a565b505050505050565b60006146988461277a565b9050811561474c5782601c60008282546146b29190615313565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906146ec908490615313565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156147475773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614741908490615313565b90915550505b6147f3565b82601c600082825461475e91906152ae565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906147989084906152ae565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156147f35773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548592906147ed9084906152ae565b90915550505b6115dc84600060015b602254640100000000900460ff1661481c57811561481c5761481c61382a565b80156148525761482b8361117d565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff83161561206757600080600061487c8661206c565b6022549295509093509150640100000000900460ff1661489f5761489f86614cf9565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c602052604090208290558281106149235760006148da84836152ae565b905080601d546148ea9190615313565b601d556148f78185615313565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550614685565b600061492f82856152ae565b905080601d5461493f91906152ae565b601d5561494c81856152ae565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614983614c90565b60005b601254811015614a6a576000601282815481106149a5576149a5615250565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614a61576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a5e91906153c5565b50505b50600101614986565b50600062093a8060045442614a7f91906152ae565b614a8991906152d8565b905060005b601054811015614c625760108181548110614aab57614aab615250565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614b22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b469190615326565b614b51836001615313565b62093a80614b5e84613387565b614b6891906152c1565b614b7291906152c1565b111560108281548110614b8757614b87615250565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614c59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2a9190615060565b50600101614a8e565b5062093a80614c72826001615313565b614c7c91906152c1565b600454614c899190615313565b6004556133845b6000614c9a61194e565b905060005b601654811015614cea57818181518110614cbb57614cbb615250565b602002602001015160168281548110614cd657614cd6615250565b600091825260209091200155600101614c9f565b50614cf3613e6a565b60055550565b73ffffffffffffffffffffffffffffffffffffffff811615613384576000614d2082610a4c565b905060005b8151811015614d8457818181518110614d4057614d40615250565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101614d25565b5060005b81518110156120675760168181548110614da457614da4615250565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff86168352601782526040808420858552909252912055600101614d88565b803573ffffffffffffffffffffffffffffffffffffffff811681146127d857600080fd5b600060208284031215614e1b57600080fd5b613a9f82614de5565b6020808252825182820181905260009190848201906040850190845b81811015614e5c57835183529284019291840191600101614e40565b50909695505050505050565b801515811461338457600080fd5b600080600060608486031215614e8b57600080fd5b83359250614e9b60208501614de5565b91506040840135614eab81614e68565b809150509250925092565b600060208284031215614ec857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614e5c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614eeb565b60008060408385031215614f3057600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614fa05781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614f5c565b5091979650505050505050565b60008060408385031215614fc057600080fd5b614fc983614de5565b9150614fd760208401614de5565b90509250929050565b60008060008060808587031215614ff657600080fd5b843561500181614e68565b9350602085013561501181614e68565b9250604085013561502181614e68565b9150606085013561503181614e68565b939692955090935050565b60005b8381101561505757818101518382015260200161503f565b50506000910152565b602081526000825180602084015261507f81604085016020870161503c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156150c457600080fd5b6150cd83614de5565b946020939093013593505050565b600080604083850312156150ee57600080fd5b6150f783614de5565b9150602083013561510781614e68565b809150509250929050565b6000806000806080858703121561512857600080fd5b61513185614de5565b93506020850135925061514660408601614de5565b915061515460608601614de5565b905092959194509250565b60006020828403121561517157600080fd5b8135613a9f81614e68565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c082840312156151bd57600080fd5b82601f8301126151cc57600080fd5b60405160c0810181811067ffffffffffffffff82111715615216577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561522b57600080fd5b845b8181101561524557803583526020928301920161522d565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610ce857610ce861527f565b8082028115828204841417610ce857610ce861527f565b60008261530e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610ce857610ce861527f565b60006020828403121561533857600080fd5b5051919050565b600181811c9082168061535357607f821691505b602082108103610bbb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000825161539e81846020870161503c565b9190910192915050565b6000602082840312156153ba57600080fd5b8151613a9f81614e68565b600080604083850312156153d857600080fd5b50508051602090910151909290915056fea264697066735822122004376bfec6e2db1dffd677da8ca0af68ab52621d1a5167a1ec4919820cf5b38364736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000007b465174a93a6d0602fd4ea99eec86c07e5e156800000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0xD533a949740bb3306d119CC777fa900bA034cd52,0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [3] : _rewardRates (uint256[]): 115740740740,0,0
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [6] : _stakingToken (address): 0x7B465174A93a6d0602fD4ea99eEc86C07e5E1568
-----Encoded View---------------
27 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [5] : 00000000000000000000000000000000000000000000000000000000000002e0
Arg [6] : 0000000000000000000000007b465174a93a6d0602fd4ea99eec86c07e5e1568
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd52
Arg [10] : 0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [12] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [16] : 0000000000000000000000000000000000000000000000000000001af2af8c84
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [24] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
104616:1553:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47303:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99943:316;;;;;;:::i;:::-;;:::i;:::-;;;1700:25:1;;;1688:2;1673:18;99943:316:0;1554:177:1;50201:222:0;;;;;;:::i;:::-;;:::i;45305:109::-;;;:::i;:::-;;;;;;;:::i;30186:141::-;;;;;;:::i;:::-;;:::i;:::-;;97507:190;;;;;;:::i;:::-;;:::i;48011:339::-;;;:::i;91274:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;51033:179::-;;;;;;:::i;:::-;;:::i;80055:23::-;;;;;;;;;;;;4248:42:1;4236:55;;;4218:74;;4206:2;4191:18;80055:23:0;4058:240:1;44717:459:0;;;;;;:::i;:::-;;:::i;:::-;;;4733:14:1;;4726:22;4708:41;;4696:2;4681:18;44717:459:0;4568:187:1;41163:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;53560:1752;;;;;;:::i;:::-;;:::i;70568:572::-;;;;;;:::i;:::-;;:::i;49412:127::-;;;;;;:::i;:::-;49505:26;;49478:7;49505:26;;;:17;:26;;;;;;;49412:127;39999:48;;40041:6;39999:48;;60221:309;;;;;;:::i;:::-;;:::i;39588:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;104704:56;;;:::i;:::-;;;;;;;:::i;79867:29::-;;;;;;;;;52195:181;;;;;;:::i;:::-;;:::i;29954:29::-;;;;;;;;;41996:31;;;:::i;105652:514::-;;;:::i;49020:111::-;49101:22;;49020:111;;39909:55;;;;;;:::i;:::-;;;;;;;;;;;;;;40391:54;;;;;;:::i;:::-;;;;;;;;;;;;;;38791:32;;;;;;46310:681;;;:::i;79616:45::-;;;;;;;;;;;;86465:2692;;;;;;:::i;:::-;;:::i;61478:206::-;;;;;;:::i;:::-;;:::i;80977:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;7711:25:1;;;7767:2;7752:18;;7745:34;;;;7795:18;;;7788:34;;;;7853:2;7838:18;;7831:34;7896:3;7881:19;;7874:35;7698:3;7683:19;80977:53:0;7452:463:1;30335:271:0;;;:::i;40958:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;52572:199;;;;;;:::i;:::-;;:::i;71936:1099::-;;;;;;:::i;:::-;;:::i;41936:34::-;;;;;;;;;;;;89218:1961;;;;;;:::i;:::-;;:::i;:::-;;;;8122:25:1;;;8178:2;8163:18;;8156:34;;;;8206:18;;;8199:34;8110:2;8095:18;89218:1961:0;7920:319:1;29927:20:0;;;;;;;;;71540:161;;;;;;:::i;:::-;;:::i;41285:26::-;;;;;;;;;51489:224;;;;;;:::i;:::-;;:::i;38912:55::-;;;;;;94115:1555;;;;;;:::i;:::-;;:::i;38636:62::-;;;;;;61016:172;;;;;;:::i;:::-;;:::i;52924:444::-;;;;;;:::i;:::-;;:::i;38482:29::-;;;;;;91483:133;;;;;;:::i;:::-;91580:21;;91553:7;91580:21;;;:12;:21;;;;;:28;;91483:133;38562:50;;;;;;38155:30;;;;;;95724:1648;;;;;;:::i;:::-;;:::i;50658:166::-;;;;;;:::i;:::-;;:::i;75010:483::-;;;;;;:::i;:::-;;:::i;56332:800::-;;;;;;:::i;:::-;;:::i;48778:128::-;;;;;;:::i;:::-;48872:26;;48845:7;48872:26;;;:17;:26;;;;;;;48778:128;75813:207;;;;;;:::i;:::-;;:::i;48513:113::-;48595:23;;48513:113;;71304:97;;;:::i;55566:610::-;;;;;;:::i;:::-;;:::i;38375:27::-;;;;;;39050:51;;;;;;39126:59;;;;;;45788:452;;;;;;:::i;:::-;;:::i;68629:761::-;;;;;;:::i;:::-;;:::i;73498:958::-;;;;;;:::i;:::-;;:::i;69489:482::-;;;:::i;47303:529::-;47357:27;47397;47427:17;:15;:17::i;:::-;47482:12;:19;47397:47;;-1:-1:-1;47468:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47468:34:0;-1:-1:-1;47519:26:0;;;47548:1;47519:26;;;:17;:26;;;;;;47455:47;;-1:-1:-1;47519:30:0;47515:310;;47570:9;47565:249;47589:12;:19;47585:23;;47565:249;;;47779:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;47698:32;;;:23;:32;;;;;:35;;;;;;;;;47682:13;;47738:4;;47698:35;47682:10;;47796:1;;47682:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;47652:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;47651:91;;;;:::i;:::-;47650:148;;;;:::i;:::-;47634:10;47645:1;47634:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;47610:3;;47565:249;;;;47515:310;47386:446;47303:529;;;:::o;99943:316::-;100074:7;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;;;;;;;;;34203:1;34942:18;;100102:17:::1;::::0;::::1;::::0;::::1;;;:26;100094:57;;;::::0;::::1;::::0;;11915:2:1;100094:57:0::1;::::0;::::1;11897:21:1::0;11954:2;11934:18;;;11927:30;11993:20;11973:18;;;11966:48;12031:18;;100094:57:0::1;11713:342:1::0;100094:57:0::1;100169:82;100185:10;100197:19;100218:6;100226:24;100169:15;:82::i;:::-;34159:1:::0;35121:7;:22;100162:89;99943:316;-1:-1:-1;;;;99943:316:0:o;50201:222::-;50310:19;;50375:28;;50260:7;;50287:127;;50345:26;50310:19;50345:4;:26;:::i;:::-;50344:59;;;;:::i;:::-;50287:8;:127::i;:::-;50280:134;50201:222;-1:-1:-1;;50201:222:0:o;45305:109::-;45358:16;45394:12;45387:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45305:109;:::o;30186:141::-;30666:5;;;;30652:10;:19;30644:79;;;;;;;12262:2:1;30644:79:0;;;12244:21:1;12301:2;12281:18;;;12274:30;12340:34;12320:18;;;12313:62;12411:17;12391:18;;;12384:45;12446:19;;30644:79:0;12060:411:1;30644:79:0;30258:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;30297:22:::1;::::0;4218:74:1;;;30297:22:0::1;::::0;4206:2:1;4191:18;30297:22:0::1;;;;;;;30186:141:::0;:::o;97507:190::-;97592:7;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;97619:70:::1;97632:10;::::0;97656:9;97667:4;97673:15:::1;97619:12;:70::i;:::-;34159:1:::0;35121:7;:22;97612:77;97507:190;-1:-1:-1;;;97507:190:0:o;48011:339::-;48161:17;:24;48066:41;;48147:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48147:39:0;;48120:66;;48204:9;48199:144;48223:17;:24;48219:28;;48199:144;;;40041:6;48299:14;48311:1;48299:11;:14::i;:::-;:32;;;;:::i;:::-;48269:24;48294:1;48269:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;48249:3;;48199:144;;;;48011:339;:::o;91274:133::-;91378:21;;;;;;;:12;:21;;;;;;;;91371:28;;;;;;;;;;;;;;;;;91338:20;;91371:28;;91378:21;;91371:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91274:133;;;:::o;51033:179::-;51148:32;;;51102:7;51148:32;;;:17;:32;;;;;;51130:15;;38283:4;;51130:50;;;:::i;:::-;51129:75;;;;:::i;44717:459::-;44834:32;;;44813:4;44834:32;;;:13;:32;;;;;;;;44829:297;;-1:-1:-1;44875:5:0;44868:12;;44829:297;44900:25;;;;;:60;;-1:-1:-1;44929:31:0;;;;44900:60;44896:230;;;-1:-1:-1;44969:5:0;44962:12;;44896:230;45009:5;;;;;;44994:20;;;;44990:136;;-1:-1:-1;45023:4:0;45016:11;;44990:136;45065:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;45061:65;;-1:-1:-1;45122:4:0;45115:11;;45061:65;-1:-1:-1;45162:5:0;44717:459;;;;:::o;53560:1752::-;53623:24;;;53784:20;53796:7;53784:11;:20::i;:::-;53764:40;-1:-1:-1;53835:23:0;;;;53834:81;;53889:26;;;;;4248:42:1;4236:55;;53889:26:0;;;4218:74:1;37890:42:0;;53889:15;;4191:18:1;;53889:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53834:81;;;53862:24;;;;;4248:42:1;4236:55;;53862:24:0;;;4218:74:1;37890:42:0;;53862:15;;4191:18:1;;53862:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53815:100;;54021:19;38283:4;37890:42;54145:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;54086:24;;54063:20;;54044:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;54043:145;;;;:::i;:::-;54021:167;-1:-1:-1;54297:19:0;;54512:23;;;;54511:94;;54570:35;54595:9;54570:24;:35::i;:::-;54511:94;;;54539:28;54559:7;54539:19;:28::i;:::-;54482:123;-1:-1:-1;54626:30:0;;54622:323;;54677:27;54751:26;54708:39;38283:4;54708:16;:39;:::i;:::-;54707:70;;;;:::i;:::-;54677:100;;38283:4;54851:20;;54829:19;:42;;;;:::i;:::-;54828:67;;;;:::i;:::-;54814:81;;54657:254;54622:323;;;54944:1;54930:15;;54622:323;54327:699;55113:11;55099;:25;:53;;55141:11;55099:53;;;55127:11;55099:53;55079:74;;55243:20;;55224:16;:39;55220:84;;;55284:20;;55265:39;;55220:84;53649:1663;;;;53560:1752;;;:::o;70568:572::-;42206:5;;;;42192:10;:19;;:79;;-1:-1:-1;42229:42:0;42215:10;:56;42192:79;42184:113;;;;;;;12867:2:1;42184:113:0;;;12849:21:1;12906:2;12886:18;;;12879:30;12945:23;12925:18;;;12918:51;12986:18;;42184:113:0;12665:345:1;42184:113:0;70770:13:::1;:30:::0;;70811:38;;70770:30;;::::1;;;70811:38:::0;;;70770:30:::1;70811:38:::0;::::1;;;;70860:50:::0;::::1;::::0;;::::1;;;;::::0;;71051:23;:50;::::1;;;-1:-1:-1::0;71079:22:0::1;::::0;;;::::1;;;71078:23;71051:50;71048:84;;;71103:22;:29:::0;;;::::1;::::0;::::1;::::0;;71048:84:::1;70568:572:::0;;;;:::o;60221:309::-;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;60319:22:::1;::::0;;;::::1;;;60318:23;60310:60;;;::::0;::::1;::::0;;13217:2:1;60310:60:0::1;::::0;::::1;13199:21:1::0;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;60310:60:0::1;13015:348:1::0;60310:60:0::1;60389:23;::::0;;;::::1;;;:32;60381:70;;;::::0;::::1;::::0;;13570:2:1;60381:70:0::1;::::0;::::1;13552:21:1::0;13609:2;13589:18;;;13582:30;13648:27;13628:18;;;13621:55;13693:18;;60381:70:0::1;13368:349:1::0;60381:70:0::1;-1:-1:-1::0;34159:1:0;35121:7;:22;60221:309::o;104704:56::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;52195:181::-;52262:7;38283:4;52316:28;;52290:23;52305:7;52290:14;:23::i;:::-;:54;;;;:::i;41996:31::-;;;;;;;:::i;105652:514::-;106119:9;;:24;;;;;;;;105708:25;;106119:9;;;:22;;:24;;;;;;;;;;;;;;:9;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106115:28;;:1;:28;:::i;:::-;106081:9;;;;;;;;;;;:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:29;;106105:4;106081:29;:::i;:::-;106080:64;;;;:::i;:::-;106060:84;;105652:514;:::o;46310:681::-;46358:41;46416:23;;46443:1;46416:28;:59;;;-1:-1:-1;46448:22:0;;:27;46416:59;46412:572;;;46499:21;46492:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46310:681;:::o;46412:572::-;46603:12;:19;46589:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46589:34:0;;46562:61;;46643:9;46638:289;46662:21;:28;46658:32;;46638:289;;;46870:22;;46845:14;46857:1;46845:11;:14::i;:::-;46827;;46798:26;:24;:26::i;:::-;:43;;;;:::i;:::-;46797:62;;;;:::i;:::-;:69;;46862:4;46797:69;:::i;:::-;46796:96;;;;:::i;:::-;46746:21;46768:1;46746:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;46716:24;46741:1;46716:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;46692:3;;46638:289;;86465:2692;86656:21;;;86554:32;86656:21;;;:12;:21;;;;;:32;;86554;;86656:21;86678:9;;86656:32;;;;;;:::i;:::-;;;;;;;;;86625:63;;;;;;;;86656:32;;;;;;;86625:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86871:28;;;;;:19;:28;;;;;;86625:63;;-1:-1:-1;;86867:224:0;;;-1:-1:-1;86964:25:0;;;;86867:224;;;-1:-1:-1;87051:28:0;;;;;;;:19;:28;;;;;;86867:224;87180:15;87150:9;:26;;;:45;87146:1802;;87375:26;;;;87344:28;;;;;;;:19;:28;;;;;;:57;87340:1087;;;87421:26;87479:17;87450:9;:26;;;:46;;;;:::i;:::-;87421:75;;87515:25;87561:9;:26;;;87543:15;:44;;;;:::i;:::-;87515:72;-1:-1:-1;87667:33:0;87703:38;87718:22;87739:1;87718:18;:22;:::i;87703:38::-;87667:74;-1:-1:-1;87958:17:0;88030:21;88034:17;87958;88030:21;:::i;:::-;87979:46;88007:18;87979:25;:46;:::i;:::-;87978:74;;;;:::i;:::-;87958:94;-1:-1:-1;88111:38:0;88132:17;88111:18;:38;:::i;:::-;88098:52;;:9;:52;:::i;:::-;88071:79;;87402:764;;;;87146:1802;;87340:1087;88410:1;88383:28;;87146:1802;;;88572:21;88627:20;88679:17;88650:9;:26;;;:46;;;;:::i;:::-;88627:69;;88715:20;88767:15;88738:9;:26;;;:44;;;;:::i;:::-;88715:67;-1:-1:-1;88849:1:0;88818:27;88715:67;88818:12;:27;:::i;:::-;88817:33;;;;:::i;:::-;88801:49;;88608:258;;88907:29;88922:13;88907:14;:29::i;:::-;88880:56;;88492:456;87146:1802;89070:9;:25;;;89043:24;:52;89039:110;;;89124:9;:25;;;89097:52;;89039:110;86588:2569;;86465:2692;;;;:::o;61478:206::-;61580:16;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;61616:60:::1;61627:10;61639:19:::0;61660:15;61616:10:::1;:60::i;80977:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;80977:53:0;;-1:-1:-1;80977:53:0;;;:::o;30335:271::-;30404:14;;;;30390:10;:28;30382:94;;;;;;;14366:2:1;30382:94:0;;;14348:21:1;14405:2;14385:18;;;14378:30;14444:34;14424:18;;;14417:62;14515:23;14495:18;;;14488:51;14556:19;;30382:94:0;14164:417:1;30382:94:0;30505:5;;;30512:14;30492:35;;;30505:5;;;;14821:34:1;;30512:14:0;;;;14886:2:1;14871:18;;14864:43;30492:35:0;;14733:18:1;30492:35:0;;;;;;;30546:14;;;;30538:22;;;;;;30546:14;;;30538:22;;;;30571:27;;;30335:271::o;52572:199::-;52650:7;38283:4;52711:28;;52678:30;52694:13;52678:15;:30::i;71936:1099::-;42409:5;;72022:12;;42409:5;;42395:10;:19;;:74;;;42418:51;42436:10;42448:20;42418:17;:51::i;:::-;42387:107;;;;;;;15120:2:1;42387:107:0;;;15102:21:1;15159:2;15139:18;;;15132:30;15198:22;15178:18;;;15171:50;15238:18;;42387:107:0;14918:344:1;42387:107:0;72120:27:::1;::::0;::::1;72104:13;72120:27:::0;;;:13:::1;:27;::::0;;;;;::::1;;::::0;72374:54;::::1;;;-1:-1:-1::0;72386:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;72418:10;72386:42;72374:54;72373:113;;;;72452:8;72451:9;:34;;;;-1:-1:-1::0;72479:5:0::1;::::0;::::1;;72465:10;:19;72451:34;72351:677;;;72798:66;72826:12;72840:10;72852:11;72798:27;:66::i;72351:677::-;72980:36;::::0;::::1;::::0;;15469:2:1;72980:36:0::1;::::0;::::1;15451:21:1::0;15508:2;15488:18;;;15481:30;15547:28;15527:18;;;15520:56;15593:18;;72980:36:0::1;15267:350:1::0;42505:1:0::1;71936:1099:::0;;;:::o;89218:1961::-;89521:26;;;89319:27;89521:26;;;:17;:26;;;;;;;89319:27;89708:24;89539:7;89708:15;:24::i;:::-;89808:26;;;89745:33;89808:26;;;:17;:26;;;;;;89685:47;;-1:-1:-1;89745:33:0;89808:31;:66;;;;-1:-1:-1;89843:26:0;;;;;;;:17;:26;;;;;;:31;89808:66;89807:143;;;-1:-1:-1;89918:31:0;;;;;;;:22;:31;;;;;;89894:55;;;89807:143;89789:638;;;-1:-1:-1;90191:20:0;89789:638;;;90379:31;;;;;;;:22;:31;;;;;;90414:1;;90356:54;;:20;:54;:::i;:::-;90355:60;;;;:::i;:::-;90327:88;;89789:638;90562:1;90540:23;;90579:9;90574:598;90598:21;;;;;;;:12;:21;;;;;:28;90594:32;;90574:598;;;90679:21;;;90648:28;90679:21;;;:12;:21;;;;;:24;;90701:1;;90679:24;;;;;;:::i;:::-;;;;;;;;;;;90648:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90775:32;90810:34;90833:7;90842:1;90810:22;:34::i;:::-;90926:19;;;;90775:69;;-1:-1:-1;90906:17:0;38283:4;91021:52;91048:25;90775:69;91021:52;:::i;:::-;91008:66;;:9;:66;:::i;:::-;91007:91;;;;:::i;:::-;90994:105;;:9;:105;:::i;:::-;90960:139;-1:-1:-1;91114:46:0;90960:139;91114:46;;:::i;:::-;;-1:-1:-1;;90628:3:0;;;;;-1:-1:-1;90574:598:0;;-1:-1:-1;;90574:598:0;;;89448:1731;89218:1961;;;;;:::o;71540:161::-;42206:5;;;;42192:10;:19;;:79;;-1:-1:-1;42229:42:0;42215:10;:56;42192:79;42184:113;;;;;;;12867:2:1;42184:113:0;;;12849:21:1;12906:2;12886:18;;;12879:30;12945:23;12925:18;;;12918:51;12986:18;;42184:113:0;12665:345:1;42184:113:0;71661:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;71625:68;;::::1;71661:32;::::0;;::::1;71660:33;71625:68;::::0;;71540:161::o;51489:224::-;51555:7;51689:15;;51658:28;;:46;;;;:::i;:::-;51583:24;;;;;4248:42:1;4236:55;;51583:24:0;;;4218:74:1;38283:4:0;;;;37890:42;;51583:15;;4191:18:1;;51583:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;94115:1555::-;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;94256:13:::1;::::0;;;::::1;;;94255:14;94247:41;;;::::0;::::1;::::0;;15824:2:1;94247:41:0::1;::::0;::::1;15806:21:1::0;15863:2;15843:18;;;15836:30;15902:16;15882:18;;;15875:44;15936:18;;94247:41:0::1;15622:338:1::0;94247:41:0::1;94356:22;::::0;;;::::1;;;94355:23;94347:60;;;::::0;::::1;::::0;;13217:2:1;94347:60:0::1;::::0;::::1;13199:21:1::0;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;94347:60:0::1;13015:348:1::0;94347:60:0::1;94471:40;94482:10;94494;94506:4;94471:10;:40::i;:::-;;94573:28;94603:21:::0;94628:29:::1;94638:10;94650:6;94628:9;:29::i;:::-;94572:85;;;;94707:15;94747:8;94725:9;:19;;;:30;;;;:::i;:::-;94707:48:::0;-1:-1:-1;94926:12:0::1;::::0;94886:91:::1;::::0;94926:12:::1;::::0;::::1;;;94941:10;94961:4;94968:8:::0;94886:31:::1;:91::i;:::-;95326:186;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;95373:25:::0;;::::1;::::0;95326:186;;::::1;::::0;;;;;;;;95435:26;;::::1;::::0;95326:186;;;;;95476:25;;::::1;::::0;95326:186;;;;95297:10:::1;-1:-1:-1::0;95284:24:0;;;:12:::1;:24:::0;;;;;;;:39;;95309:13;;95284:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95556:42;95571:10;95583:8;95593:4;95556:14;:42::i;:::-;95616:46;::::0;;16484:25:1;;;16540:2;16525:18;;16518:34;;;95633:10:0::1;::::0;95616:46:::1;::::0;16457:18:1;95616:46:0::1;;;;;;;-1:-1:-1::0;;34159:1:0;35121:7;:22;-1:-1:-1;;;94115:1555:0:o;61016:172::-;61095:16;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;61131:49:::1;61142:10;61154:19:::0;61175:4:::1;61131:10;:49::i;:::-;34159:1:::0;35121:7;:22;61124:56;61016:172;-1:-1:-1;;61016:172:0:o;52924:444::-;53003:25;;;52980:7;53003:25;;;:19;:25;;;;;;;;52999:362;;;-1:-1:-1;53206:4:0;52924:444::o;52999:362::-;-1:-1:-1;53318:31:0;;;;;;;;:25;:31;;;;;;;;52924:444::o;52999:362::-;52924:444;;;:::o;95724:1648::-;34203:1;34809:7;;:19;34801:63;;;;;;;11555:2:1;34801:63:0;;;11537:21:1;11594:2;11574:18;;;11567:30;11633:33;11613:18;;;11606:61;11684:18;;34801:63:0;11353:355:1;34801:63:0;34203:1;34942:18;;95866:13:::1;::::0;;;::::1;;;95865:14;95857:41;;;::::0;::::1;::::0;;15824:2:1;95857:41:0::1;::::0;::::1;15806:21:1::0;15863:2;15843:18;;;15836:30;15902:16;15882:18;;;15875:44;15936:18;;95857:41:0::1;15622:338:1::0;95857:41:0::1;95966:22;::::0;;;::::1;;;95965:23;95957:60;;;::::0;::::1;::::0;;13217:2:1;95957:60:0::1;::::0;::::1;13199:21:1::0;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;95957:60:0::1;13015:348:1::0;95957:60:0::1;96081:40;96092:10;96104;96116:4;96081:10;:40::i;:::-;;96183:28;96213:21:::0;96238:29:::1;96248:10;96260:6;96238:9;:29::i;:::-;96182:85;;;;96322:15;96306:13;:31;96298:65;;;::::0;::::1;::::0;;16765:2:1;96298:65:0::1;::::0;::::1;16747:21:1::0;16804:2;16784:18;;;16777:30;16843:23;16823:18;;;16816:51;16884:18;;96298:65:0::1;16563:345:1::0;96298:65:0::1;96409:17;96459:15;96430:9;:26;;;:44;96429:97;;96525:1;96429:97;;;96507:15;96478:9;:26;;;:44;;;;:::i;:::-;96409:117:::0;-1:-1:-1;96537:16:0::1;96556:31;96572:15;96556:13:::0;:31:::1;:::i;:::-;96537:50;;96693:9;96682:8;:20;96674:57;;;::::0;::::1;::::0;;17115:2:1;96674:57:0::1;::::0;::::1;17097:21:1::0;17154:2;17134:18;;;17127:30;17193:26;17173:18;;;17166:54;17237:18;;96674:57:0::1;16913:348:1::0;96674:57:0::1;96762:13;;96750:8;:25;;96742:64;;;::::0;::::1;::::0;;17468:2:1;96742:64:0::1;::::0;::::1;17450:21:1::0;17507:2;17487:18;;;17480:30;17546:28;17526:18;;;17519:56;17592:18;;96742:64:0::1;17266:350:1::0;96742:64:0::1;96837:28;;96825:8;:40;;96817:80;;;::::0;::::1;::::0;;17823:2:1;96817:80:0::1;::::0;::::1;17805:21:1::0;17862:2;17842:18;;;17835:30;17901:29;17881:18;;;17874:57;17948:18;;96817:80:0::1;17621:351:1::0;96817:80:0::1;96981:174;;;;;;;;97007:6;96981:174;;;;97028:15;96981:174;;;;97058:9;:19;;;96981:174;;;;97092:13;96981:174;;;;97120:24;97135:8;97120:14;:24::i;:::-;96981:174:::0;;96952:10:::1;96939:24;::::0;;;:12:::1;:24;::::0;;;;:39;;96964:13;;96939:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97224:48;97248:10;97260:5;97267:4;97224:23;:48::i;:::-;97290:74;::::0;;18208:25:1;;;18264:2;18249:18;;18242:34;;;97333:15:0::1;18292:18:1::0;;;18285:34;18350:2;18335:18;;18328:34;;;97290:74:0;;97303:10:::1;::::0;97290:74:::1;::::0;;;;;18195:3:1;97290:74:0;;::::1;-1:-1:-1::0;;34159:1:0;35121:7;:22;-1:-1:-1;;;;95724:1648:0:o;50658:166::-;50766:26;;;50720:7;50766:26;;;:17;:26;;;;;;50748:15;;38283:4;;50748:44;;;:::i;75010:483::-;42409:5;;75176:20;;42409:5;;42395:10;:19;;:74;;;42418:51;42436:10;42448:20;42418:17;:51::i;:::-;42387:107;;;;;;;15120:2:1;42387:107:0;;;15102:21:1;15159:2;15139:18;;;15132:30;15198:22;15178:18;;;15171:50;15238:18;;42387:107:0;14918:344:1;42387:107:0;75227:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;75209:17:::1;:61:::0;;75273:9;;75227:42;75209:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;75356:25;75293:16;75310:20;:42;75331:20;75310:42;;;;;;;;;;;;;;;;75293:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;75411:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;75392:18:::1;:62:::0;;75457:28;;75411:42;75392:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;75010:483:::0;;;;;:::o;56332:800::-;56412:34;;;;;;;:19;:34;;;;;;;;56404:60;;;;;;;18575:2:1;56404:60:0;;;18557:21:1;18614:2;18594:18;;;18587:30;18653:15;18633:18;;;18626:43;18686:18;;56404:60:0;18373:337:1;56404:60:0;56483:36;;;;;;;:21;:36;;;;;;;;56520:10;56483:48;;;;;;;;;;56475:90;;;;;;;18917:2:1;56475:90:0;;;18899:21:1;18956:2;18936:18;;;18929:30;18995:31;18975:18;;;18968:59;19044:18;;56475:90:0;18715:353:1;56475:90:0;56711:10;56660:22;56685:37;;;:25;:37;;;;;;;;56737:28;;56733:182;;56892:10;56874:29;;;;:17;:29;;;;;;;;;;56837:33;;;;;;;;;:66;;56874:29;;56837:33;;:66;;56874:29;;56837:66;:::i;:::-;;;;-1:-1:-1;;56733:182:0;56983:10;56957:37;;;;:25;:37;;;;;;;;:53;;;;:37;:53;;;;;;;;57095:17;:29;;;;;;57059:32;;;;;;;;:65;;57095:29;;57059:32;;:65;;57095:29;;57059:65;:::i;:::-;;;;-1:-1:-1;;;;56332:800:0:o;75813:207::-;42409:5;;75921:20;;42409:5;;42395:10;:19;;:74;;;42418:51;42436:10;42448:20;42418:17;:51::i;:::-;42387:107;;;;;;;15120:2:1;42387:107:0;;;15102:21:1;15159:2;15139:18;;;15132:30;15198:22;15178:18;;;15171:50;15238:18;;42387:107:0;14918:344:1;42387:107:0;-1:-1:-1;75954:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;75813:207::o;71304:97::-;42206:5;;;;42192:10;:19;;:79;;-1:-1:-1;42229:42:0;42215:10;:56;42192:79;42184:113;;;;;;;12867:2:1;42184:113:0;;;12849:21:1;12906:2;12886:18;;;12879:30;12945:23;12925:18;;;12918:51;12986:18;;42184:113:0;12665:345:1;42184:113:0;71379:14:::1;::::0;;71361:32;;::::1;71379:14;::::0;;::::1;71378:15;71361:32;::::0;;71304:97::o;55566:610::-;55665:10;55645:31;;;;:19;:31;;;;;;;;55637:57;;;;;;;18575:2:1;55637:57:0;;;18557:21:1;18614:2;18594:18;;;18587:30;18653:15;18633:18;;;18626:43;18686:18;;55637:57:0;18373:337:1;55637:57:0;55780:10;55758:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;55757:50;55705:102;;;;;;;55910:25;:41;;;;;;;;:55;55906:263;;55981:41;;;56033:1;55981:41;;;:25;:41;;;;;;;;:54;;;;;;56124:17;:33;;;;;;56109:10;56091:29;;;;;;;:66;;56124:33;;56091:29;;:66;;56124:33;;56091:66;:::i;:::-;;;;-1:-1:-1;;55906:263:0;55566:610;:::o;45788:452::-;45849:16;45878:32;45913:16;45930:9;45913:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;45955:38:0;;45951:282;;46136:4;46094:27;46122:9;46094:38;;;;;;;;:::i;:::-;;;;;;;;;46043:24;46022:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;46021:119;;;;:::i;:::-;46010:130;;45951:282;;;46193:17;46211:9;46193:28;;;;;;;;:::i;:::-;;;;;;;;;46182:39;;45867:373;45788:452;;;:::o;68629:761::-;68746:9;68741:642;68765:16;:23;68761:27;;68741:642;;;68810:32;68845:16;68862:1;68845:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;68883:38:0;;68879:493;;68946:12;:61;;;;68981:22;69004:1;68981:25;;;;;;;;:::i;:::-;;;;;;;;;68963:15;:43;68946:61;68942:415;;;69121:106;;;;;69204:4;69121:106;;;19247:74:1;69211:15:0;19337:18:1;;;19330:34;69121:74:0;;;;;;19220:18:1;;69121:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69088:27;69116:1;69088:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;69299:24;69278:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69250:22;69273:1;69250:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;68942:415;-1:-1:-1;68790:3:0;;68741:642;;;;68629:761;:::o;73498:958::-;42206:5;;;;42192:10;:19;;:79;;-1:-1:-1;42229:42:0;42215:10;:56;42192:79;42184:113;;;;;;;12867:2:1;42184:113:0;;;12849:21:1;12906:2;12886:18;;;12879:30;12945:23;12925:18;;;12918:51;12986:18;;42184:113:0;12665:345:1;42184:113:0;73907:13;;38283:4:::1;-1:-1:-1::0;73907:37:0::1;73899:69;;;::::0;::::1;::::0;;19577:2:1;73899:69:0::1;::::0;::::1;19559:21:1::0;19616:2;19596:18;;;19589:30;19655:21;19635:18;;;19628:49;19694:18;;73899:69:0::1;19375:343:1::0;73899:69:0::1;74092:13:::0;;::::1;::::0;74109:1:::1;-1:-1:-1::0;74092:18:0;::::1;::::0;74091:44:::1;;-1:-1:-1::0;74116:13:0;;::::1;::::0;74133:1:::1;-1:-1:-1::0;74116:18:0::1;74091:44;74083:69;;;::::0;::::1;::::0;;20266:2:1;74083:69:0::1;::::0;::::1;20248:21:1::0;20305:2;20285:18;;;20278:30;20344:14;20324:18;;;20317:42;20376:18;;74083:69:0::1;20064:336:1::0;74083:69:0::1;74187:13:::0;;74165:19:::1;:35:::0;74187:13:::1;74234::::0;::::1;::::0;74211:20:::1;:36:::0;74289:13;;::::1;::::0;74258:28:::1;:44:::0;74340:13;;::::1;::::0;74313:24:::1;:40:::0;74395:13;;::::1;::::0;74364:28:::1;:44:::0;74435:13;::::1;::::0;74419::::1;:29:::0;73498:958::o;69489:482::-;69578:22;;;;;;;69577:23;69569:60;;;;;;;13217:2:1;69569:60:0;;;13199:21:1;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;69569:60:0;13015:348:1;69569:60:0;69691:25;69710:5;69691:18;:25::i;:::-;69786:16;:14;:16::i;:::-;69768:15;:34;69838:12;;69819:15;:31;69815:149;;69867:14;:12;:14::i;:::-;69489:482::o;69815:149::-;69923:29;:27;:29::i;100770:1792::-;101232:22;;100956:7;;101232:22;;;;;101228:194;;101357:53;101368:14;101384:19;101405:4;101357:10;:53::i;:::-;;101228:194;101475:28;101505:21;101530:33;101540:14;101556:6;101530:9;:33::i;:::-;101474:89;;;;101601:9;:26;;;101582:15;:45;;:71;;;-1:-1:-1;101631:14:0;;;;:22;;:14;:22;101582:71;101574:106;;;;;;;20607:2:1;101574:106:0;;;20589:21:1;20646:2;20626:18;;;20619:30;20685:24;20665:18;;;20658:52;20727:18;;101574:106:0;20405:346:1;101574:106:0;101711:19;;;;101747:13;;101743:783;;102161:12;;102125:82;;102161:12;;;;;102176:19;102197:9;102125:27;:82::i;:::-;102279:28;;;;;;;:12;:28;;;;;:43;;102308:13;;102279:43;;;;;;:::i;:::-;;;;;;;;;;;;;102272:50;;;;;;;;;;;;;;;;;;;;;;;;;;102374:48;;102389:14;;102405:9;;102374:14;:48::i;:::-;102444:70;;;20958:25:1;;;21014:2;20999:18;;20992:34;;;102444:70:0;21062:55:1;;;21042:18;;;21035:83;102444:70:0;;;;;;;;;;;20946:2:1;102444:70:0;;;101743:783;102545:9;100770:1792;-1:-1:-1;;;;;;;100770:1792:0:o;26468:106::-;26526:7;26557:1;26553;:5;:13;;26565:1;26553:13;;;26561:1;26553:13;26546:20;26468:106;-1:-1:-1;;;26468:106:0:o;97893:1688::-;98139:7;98108:14;98124:4;42600:49;42624:7;42633:8;42643:5;42600:23;:49::i;:::-;98168:22:::1;::::0;;;::::1;;;98167:23;98159:60;;;::::0;::::1;::::0;;13217:2:1;98159:60:0::1;::::0;::::1;13199:21:1::0;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;98159:60:0::1;13015:348:1::0;98159:60:0::1;98239:13;::::0;;;::::1;;;98238:14;98230:41;;;::::0;::::1;::::0;;15824:2:1;98230:41:0::1;::::0;::::1;15806:21:1::0;15863:2;15843:18;;;15836:30;15902:16;15882:18;;;15875:44;15936:18;;98230:41:0::1;15622:338:1::0;98230:41:0::1;98298:13;;98290:4;:21;;98282:60;;;::::0;::::1;::::0;;17468:2:1;98282:60:0::1;::::0;::::1;17450:21:1::0;17507:2;17487:18;;;17480:30;17546:28;17526:18;;;17519:56;17592:18;;98282:60:0::1;17266:350:1::0;98282:60:0::1;98369:28;;98361:4;:36;;98353:75;;;::::0;::::1;::::0;;17823:2:1;98353:75:0::1;::::0;::::1;17805:21:1::0;17862:2;17842:18;;;17835:30;17901:29;17881:18;;;17874:57;17948:18;;98353:75:0::1;17621:351:1::0;98353:75:0::1;98551:12;::::0;98511:96:::1;::::0;98551:12:::1;::::0;::::1;;;98566:14:::0;98590:4:::1;98597:9:::0;98511:31:::1;:96::i;:::-;98934:23;98960:20;98975:4;98960:14;:20::i;:::-;99079:33;::::0;::::1;98991:14;99079:33:::0;;;:17:::1;:33;::::0;;;;;;;;99018:95;;21375:66:1;21362:2;21358:15;;;21354:88;99018:95:0;;::::1;21342:101:1::0;;;;21459:12;;;21452:28;;;21496:12;;;21489:28;;;21533:12;;;21526:28;98934:46:0;;-1:-1:-1;98991:14:0;21570:13:1;;99018:95:0::1;::::0;;;;;::::1;::::0;;;;;;99008:106;;99018:95:::1;99008:106:::0;;::::1;::::0;99171:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;99205:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;99008:106;;-1:-1:-1;99171:28:0;99205:164;;;99306:22:::1;99324:4:::0;99252:15;99306:22:::1;:::i;:::-;99205:164:::0;;::::1;::::0;;::::1;::::0;;;99171:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;99171: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;99414:47:::1;::::0;99429:14;;99445:9;;99414:14:::1;:47::i;:::-;99479:68;::::0;;21825:25:1;;;21881:2;21866:18;;21859:34;;;21909:18;;;21902:34;;;99479:68:0::1;21972:55:1::0;;;21967:2;21952:18;;21945:83;99479:68:0;::::1;::::0;::::1;::::0;21812:3:1;21797:19;99479:68:0::1;;;;;;;99567:6:::0;97893:1688;-1:-1:-1;;;;;;;;;97893:1688:0:o;45466:133::-;45525:7;45552:39;45561:15;45578:12;;45552:8;:39::i;61780:1313::-;61928:31;61903:8;61913:4;42600:49;42624:7;42633:8;42643:5;42600:23;:49::i;:::-;62027:22:::1;::::0;;;::::1;;;62026:23;62018:60;;;::::0;::::1;::::0;;13217:2:1;62018:60:0::1;::::0;::::1;13199:21:1::0;13256:2;13236:18;;;13229:30;13295:26;13275:18;;;13268:54;13339:18;;62018:60:0::1;13015:348:1::0;62018:60:0::1;62161:23;::::0;;;::::1;;;:32;62153:70;;;::::0;::::1;::::0;;13570:2:1;62153:70:0::1;::::0;::::1;13552:21:1::0;13609:2;13589:18;;;13582:30;13648:27;13628:18;;;13621:55;13693:18;;62153:70:0::1;13368:349:1::0;62153:70:0::1;62322:29;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;62354:15:::1;62322:47:::0;;62481:12:::1;:19:::0;62467:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;62467:34:0::1;;62450:51;;62519:9;62514:419;62538:12;:19:::0;62534:23;::::1;62514:419;;;62599:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;62579:17;;:14;;62617:1;;62579:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;62634:17:::1;::::0;::::1;62657:1;62634:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;62677:17;;:14;;62652:1;;62677:17;::::1;;;;;:::i;:::-;;;;;;;:21;62673:249;;;62719:84;62747:12;62760:1;62747:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;62764:19;62785:14;62800:1;62785:17;;;;;;;;:::i;:::-;;;;;;;62719:27;:84::i;:::-;62840:8;62829:77;;;62850:14;62865:1;62850:17;;;;;;;;:::i;:::-;;;;;;;62869:12;62882:1;62869:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;62829:77:::1;::::0;;22241:25:1;;;62869:15:0::1;::::0;;::::1;22343:18:1::0;;;22336:43;;;;22415:15;;22395:18;;;22388:43;22229:2;22214:18;62829:77:0::1;;;;;;;62673:249;62559:3;;62514:419;;;;61780:1313:::0;;;;;;;:::o;31469:361::-;31664:45;;;31653:10;19265:55:1;;;31664:45:0;;;19247:74:1;19337:18;;;;19330:34;;;31664:45:0;;;;;;;;;;19220:18:1;;;;31664:45:0;;;;;;;;;;;;;31653:57;;-1:-1:-1;;;;31653:10:0;;;;:57;;31664:45;31653:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31617:93;;;;31729:7;:57;;;;-1:-1:-1;31741:11:0;;:16;;:44;;;31772:4;31761:24;;;;;;;;;;;;:::i;:::-;31721:101;;;;;;;23186:2:1;31721:101:0;;;23168:21:1;23225:2;23205:18;;;23198:30;23264:33;23244:18;;;23237:61;23315:18;;31721:101:0;22984:355:1;31721:101:0;31539:291;;31469:361;;;:::o;93462:590::-;93544:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93544:31:0;93577:15;93609:11;;93605:347;;93642:9;93637:304;93661:28;;;;;;;:12;:28;;;;;:35;93657:39;;93637:304;;;93736:28;;;;;;;:12;:28;;;;;:31;;93765:1;;93736:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;93726:6;:48;93722:204;;93813:28;;;;;;;:12;:28;;;;;:31;;93842:1;;93813:31;;;;;;:::i;:::-;;;;;;;;;;;93798:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93877:1;93867:11;;93901:5;;93722:204;93698:3;;93637:304;;;;93605:347;93970:11;;;;;:44;;-1:-1:-1;93985:19:0;;:29;;93970:44;93962:72;;;;;;;23546:2:1;93962:72:0;;;23528:21:1;23585:2;23565:18;;;23558:30;23624:17;23604:18;;;23597:45;23659:18;;93962:72:0;23344:339:1;93962:72:0;93462:590;;;;;:::o;31838:402::-;32063:51;;;32052:10;23969:15:1;;;32063:51:0;;;23951:34:1;24021:15;;;24001:18;;;23994:43;24053:18;;;;24046:34;;;32063:51:0;;;;;;;;;;23863:18:1;;;;32063:51:0;;;;;;;;;;;;;32052:63;;-1:-1:-1;;;;32052:10:0;;;;:63;;32063:51;32052:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32016:99;;;;32134:7;:57;;;;-1:-1:-1;32146:11:0;;:16;;:44;;;32177:4;32166:24;;;;;;;;;;;;:::i;:::-;32126:106;;;;;;;24293:2:1;32126:106:0;;;24275:21:1;24332:2;24312:18;;;24305:30;24371:34;24351:18;;;24344:62;24442:6;24422:18;;;24415:34;24466:19;;32126:106:0;24091:400:1;32126:106:0;31926:314;;31838:402;;;;:::o;92577:877::-;92705:17;92725:27;92737:14;92725:11;:27::i;:::-;92705:47;;92769:6;92765:561;;;92860:3;92833:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;92878:33:0;;;;;;;:17;:33;;;;;:40;;92915:3;;92878:33;:40;;92915:3;;92878:40;:::i;:::-;;;;-1:-1:-1;;92972:23:0;;;;92968:64;;92997:28;;;;;;;:17;:28;;;;;:35;;93029:3;;92997:28;:35;;93029:3;;92997:35;:::i;:::-;;;;-1:-1:-1;;92968:64:0;92765:561;;;93142:3;93115:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;93160:33:0;;;;;;;:17;:33;;;;;:40;;93197:3;;93160:33;:40;;93197:3;;93160:40;:::i;:::-;;;;-1:-1:-1;;93254:23:0;;;;93250:64;;93279:28;;;;;;;:17;:28;;;;;:35;;93311:3;;93279:28;:35;;93311:3;;93279:35;:::i;:::-;;;;-1:-1:-1;;93250:64:0;93394:52;93418:14;93434:5;93441:4;57448:1962;57634:22;;;;;;;57629:214;;57782:8;57778:54;;;57810:6;:4;:6::i;:::-;57983:19;57979:109;;;58052:24;58068:7;58052:15;:24::i;:::-;58018:31;;;;;;;:22;:31;;;;;:58;57979:109;58112:21;;;;58108:1295;;58326:27;58372:28;58419:27;58464:30;58486:7;58464:21;:30::i;:::-;58561:22;;58304:190;;-1:-1:-1;58304:190:0;;-1:-1:-1;58304:190:0;-1:-1:-1;58561:22:0;;;;;58556:49;;58585:20;58597:7;58585:11;:20::i;:::-;58681:31;;;;;;;:22;:31;;;;;:54;;;58822:42;;;58818:572;;58885:19;58907:41;58929:19;58907;:41;:::i;:::-;58885:63;;59017:11;58992:22;;:36;;;;:::i;:::-;58967:22;:61;59076:33;59098:11;59076:19;:33;:::i;:::-;59047:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;58818:572:0;;;59150:19;59172:41;59194:19;59172;:41;:::i;:::-;59150:63;;59282:11;59257:22;;:36;;;;:::i;:::-;59232:22;:61;59341:33;59363:11;59341:19;:33;:::i;:::-;59312:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;58135:1268:0;;;57448:1962;;;:::o;63180:4846::-;63267:29;:27;:29::i;:::-;63386:9;63381:327;63405:18;:25;63401:29;;63381:327;;;63452:34;63489:18;63508:1;63489:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;63529:40:0;;63525:172;;63590:91;;;;;63675:4;63590:91;;;4218:74:1;63590:76:0;;;;;;4191:18:1;;63590:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;63525:172;-1:-1:-1;63432:3:0;;63381:327;;;;64068:27;40041:6;64124:12;;64106:15;:30;;;;:::i;:::-;64098:57;;;;:::i;:::-;64068:87;;64294:9;64289:284;64313:12;:19;64309:23;;64289:284;;;64435:12;64448:1;64435:15;;;;;;;;:::i;:::-;;;;;;;;;;;64428:48;;;;;64470:4;64428:48;;;4218:74:1;64435:15:0;;;;;64428:33;;4191:18:1;;64428:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64399:23;:19;64421:1;64399:23;:::i;:::-;40041:6;64363:14;64375:1;64363:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;64362:114;;64542:12;64555:1;64542:15;;;;;;;;:::i;:::-;;;;;;;;;;;;64485:73;;;24988:34:1;64485:73:0;;;24976:47:1;;;;25053:6;25039:12;;;25032:28;25098:2;25094:15;;;25076:12;;;25069:110;25195:12;;64485:73:0;;;;;;;;;;;;64354:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;64334:3:0;;64289:284;;;-1:-1:-1;40041:6:0;64785:23;:19;64807:1;64785:23;:::i;:::-;64784:43;;;;:::i;:::-;64768:12;;:60;;;;:::i;:::-;64753:12;:75;67989:29;68034:435;68121:34;68158:17;:15;:17::i;:::-;68121:54;;68238:9;68233:133;68257:21;:28;68253:32;;68233:133;;;68334:17;68352:1;68334:20;;;;;;;;:::i;:::-;;;;;;;68307:21;68329:1;68307:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;68287:3;;68233:133;;;;68435:26;:24;:26::i;:::-;68418:14;:43;-1:-1:-1;68034:435:0:o;59418:585::-;59480:21;;;;59476:520;;59557:27;59587:15;59594:7;59587:6;:15::i;:::-;59557:45;;59665:9;59660:118;59684:10;:17;59680:1;:21;59660:118;;;59749:10;59760:1;59749:13;;;;;;;;:::i;:::-;;;;;;;;;;;;59727:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;59703:3;;59660:118;;;;59845:9;59840:145;59864:10;:17;59860:1;:21;59840:145;;;59945:21;59967:1;59945:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;59907:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;59883:3;;59840:145;;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:118::-;1129:5;1122:13;1115:21;1108:5;1105:32;1095:60;;1151:1;1148;1141:12;1166:383;1240:6;1248;1256;1309:2;1297:9;1288:7;1284:23;1280:32;1277:52;;;1325:1;1322;1315:12;1277:52;1361:9;1348:23;1338:33;;1390:38;1424:2;1413:9;1409:18;1390:38;:::i;:::-;1380:48;;1478:2;1467:9;1463:18;1450:32;1491:28;1513:5;1491:28;:::i;:::-;1538:5;1528:15;;;1166:383;;;;;:::o;1736:180::-;1795:6;1848:2;1836:9;1827:7;1823:23;1819:32;1816:52;;;1864:1;1861;1854:12;1816:52;-1:-1:-1;1887:23:1;;1736:180;-1:-1:-1;1736:180:1:o;1921:681::-;2092:2;2144:21;;;2214:13;;2117:18;;;2236:22;;;2063:4;;2092:2;2315:15;;;;2289:2;2274:18;;;2063:4;2358:218;2372:6;2369:1;2366:13;2358:218;;;2437:13;;2452:42;2433:62;2421:75;;2551:15;;;;2516:12;;;;2394:1;2387:9;2358:218;;2607:248;2675:6;2683;2736:2;2724:9;2715:7;2711:23;2707:32;2704:52;;;2752:1;2749;2742:12;2704:52;-1:-1:-1;;2775:23:1;;;2845:2;2830:18;;;2817:32;;-1:-1:-1;2607:248:1:o;3042:1011::-;3271:2;3323:21;;;3393:13;;3296:18;;;3415:22;;;3242:4;;3271:2;3456;;3474:18;;;;3515:15;;;3242:4;3558:469;3572:6;3569:1;3566:13;3558:469;;;3631:13;;3669:9;;3657:22;;3719:11;;;3713:18;3699:12;;;3692:40;3772:11;;;3766:18;3752:12;;;3745:40;3808:4;3852:11;;;3846:18;3832:12;;;3825:40;3888:4;3932:11;;;3926:18;3912:12;;;3905:40;3974:4;3965:14;;;;4002:15;;;;3594:1;3587:9;3558:469;;;-1:-1:-1;4044:3:1;;3042:1011;-1:-1:-1;;;;;;;3042:1011:1:o;4303:260::-;4371:6;4379;4432:2;4420:9;4411:7;4407:23;4403:32;4400:52;;;4448:1;4445;4438:12;4400:52;4471:29;4490:9;4471:29;:::i;:::-;4461:39;;4519:38;4553:2;4542:9;4538:18;4519:38;:::i;:::-;4509:48;;4303:260;;;;;:::o;4991:647::-;5065:6;5073;5081;5089;5142:3;5130:9;5121:7;5117:23;5113:33;5110:53;;;5159:1;5156;5149:12;5110:53;5198:9;5185:23;5217:28;5239:5;5217:28;:::i;:::-;5264:5;-1:-1:-1;5321:2:1;5306:18;;5293:32;5334:30;5293:32;5334:30;:::i;:::-;5383:7;-1:-1:-1;5442:2:1;5427:18;;5414:32;5455:30;5414:32;5455:30;:::i;:::-;5504:7;-1:-1:-1;5563:2:1;5548:18;;5535:32;5576:30;5535:32;5576:30;:::i;:::-;4991:647;;;;-1:-1:-1;4991:647:1;;-1:-1:-1;;4991:647:1:o;5643:250::-;5728:1;5738:113;5752:6;5749:1;5746:13;5738:113;;;5828:11;;;5822:18;5809:11;;;5802:39;5774:2;5767:10;5738:113;;;-1:-1:-1;;5885:1:1;5867:16;;5860:27;5643:250::o;5898:455::-;6047:2;6036:9;6029:21;6010:4;6079:6;6073:13;6122:6;6117:2;6106:9;6102:18;6095:34;6138:79;6210:6;6205:2;6194:9;6190:18;6185:2;6177:6;6173:15;6138:79;:::i;:::-;6269:2;6257:15;6274:66;6253:88;6238:104;;;;6344:2;6234:113;;5898:455;-1:-1:-1;;5898:455:1:o;6873:254::-;6941:6;6949;7002:2;6990:9;6981:7;6977:23;6973:32;6970:52;;;7018:1;7015;7008:12;6970:52;7041:29;7060:9;7041:29;:::i;:::-;7031:39;7117:2;7102:18;;;;7089:32;;-1:-1:-1;;;6873:254:1:o;7132:315::-;7197:6;7205;7258:2;7246:9;7237:7;7233:23;7229:32;7226:52;;;7274:1;7271;7264:12;7226:52;7297:29;7316:9;7297:29;:::i;:::-;7287:39;;7376:2;7365:9;7361:18;7348:32;7389:28;7411:5;7389:28;:::i;:::-;7436:5;7426:15;;;7132:315;;;;;:::o;8497:403::-;8583:6;8591;8599;8607;8660:3;8648:9;8639:7;8635:23;8631:33;8628:53;;;8677:1;8674;8667:12;8628:53;8700:29;8719:9;8700:29;:::i;:::-;8690:39;;8776:2;8765:9;8761:18;8748:32;8738:42;;8799:38;8833:2;8822:9;8818:18;8799:38;:::i;:::-;8789:48;;8856:38;8890:2;8879:9;8875:18;8856:38;:::i;:::-;8846:48;;8497:403;;;;;;;:::o;8905:241::-;8961:6;9014:2;9002:9;8993:7;8989:23;8985:32;8982:52;;;9030:1;9027;9020:12;8982:52;9069:9;9056:23;9088:28;9110:5;9088:28;:::i;9151:184::-;9203:77;9200:1;9193:88;9300:4;9297:1;9290:15;9324:4;9321:1;9314:15;9340:915;9422:6;9475:3;9463:9;9454:7;9450:23;9446:33;9443:53;;;9492:1;9489;9482:12;9443:53;9541:7;9534:4;9523:9;9519:20;9515:34;9505:62;;9563:1;9560;9553:12;9505:62;9596:2;9590:9;9638:3;9630:6;9626:16;9708:6;9696:10;9693:22;9672:18;9660:10;9657:34;9654:62;9651:242;;;9749:77;9746:1;9739:88;9850:4;9847:1;9840:15;9878:4;9875:1;9868:15;9651:242;9909:2;9902:22;9944:6;9988:3;9973:19;;10004;;;10001:39;;;10036:1;10033;10026:12;10001:39;10060:9;10078:146;10094:6;10089:3;10086:15;10078:146;;;10162:17;;10150:30;;10209:4;10200:14;;;;10111;10078:146;;;-1:-1:-1;10243:6:1;;9340:915;-1:-1:-1;;;;;9340:915:1:o;10260:184::-;10312:77;10309:1;10302:88;10409:4;10406:1;10399:15;10433:4;10430:1;10423:15;10449:184;10501:77;10498:1;10491:88;10598:4;10595:1;10588:15;10622:4;10619:1;10612:15;10638:128;10705:9;;;10726:11;;;10723:37;;;10740:18;;:::i;10771:168::-;10844:9;;;10875;;10892:15;;;10886:22;;10872:37;10862:71;;10913:18;;:::i;10944:274::-;10984:1;11010;11000:189;;11045:77;11042:1;11035:88;11146:4;11143:1;11136:15;11174:4;11171:1;11164:15;11000:189;-1:-1:-1;11203:9:1;;10944:274::o;11223:125::-;11288:9;;;11309:10;;;11306:36;;;11322:18;;:::i;12476:184::-;12546:6;12599:2;12587:9;12578:7;12574:23;12570:32;12567:52;;;12615:1;12612;12605:12;12567:52;-1:-1:-1;12638:16:1;;12476:184;-1:-1:-1;12476:184:1:o;13722:437::-;13801:1;13797:12;;;;13844;;;13865:61;;13919:4;13911:6;13907:17;13897:27;;13865:61;13972:2;13964:6;13961:14;13941:18;13938:38;13935:218;;14009:77;14006:1;13999:88;14110:4;14107:1;14100:15;14138:4;14135:1;14128:15;22442:287;22571:3;22609:6;22603:13;22625:66;22684:6;22679:3;22672:4;22664:6;22660:17;22625:66;:::i;:::-;22707:16;;;;;22442:287;-1:-1:-1;;22442:287:1:o;22734:245::-;22801:6;22854:2;22842:9;22833:7;22829:23;22825:32;22822:52;;;22870:1;22867;22860:12;22822:52;22902:9;22896:16;22921:28;22943:5;22921:28;:::i;24496:245::-;24575:6;24583;24636:2;24624:9;24615:7;24611:23;24607:32;24604:52;;;24652:1;24649;24642:12;24604:52;-1:-1:-1;;24675:16:1;;24731:2;24716:18;;;24710:25;24675:16;;24710:25;;-1:-1:-1;24496:245:1:o
Swarm Source
ipfs://04376bfec6e2db1dffd677da8ca0af68ab52621d1a5167a1ec4919820cf5b383
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.