More Info
Private Name Tags
ContractCreator
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Get Reward2 | 19959446 | 127 days ago | IN | 0 ETH | 0.00451941 | ||||
Sync | 19913710 | 133 days ago | IN | 0 ETH | 0.03519502 | ||||
Sync_gauge_weigh... | 19881159 | 138 days ago | IN | 0 ETH | 0.0004468 | ||||
Sync_gauge_weigh... | 19880611 | 138 days ago | IN | 0 ETH | 0.00039261 | ||||
Stake Locked | 19828477 | 145 days ago | IN | 0 ETH | 0.00442999 | ||||
Stake Locked | 19734912 | 158 days ago | IN | 0 ETH | 0.00815687 | ||||
0x671bc16d | 19734857 | 158 days ago | IN | 0 ETH | 0.08041355 |
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_frxETH
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-04-25 */ // 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/ICurveStableSwapNG.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface ICurveStableSwapNG { function exchange ( int128 i, int128 j, uint256 _dx, uint256 _min_dy ) external returns ( uint256 ); function exchange ( int128 i, int128 j, uint256 _dx, uint256 _min_dy, address _receiver ) external returns ( uint256 ); function exchange_received ( int128 i, int128 j, uint256 _dx, uint256 _min_dy ) external returns ( uint256 ); function exchange_received ( int128 i, int128 j, uint256 _dx, uint256 _min_dy, address _receiver ) external returns ( uint256 ); function add_liquidity ( uint256[] memory _amounts, uint256 _min_mint_amount ) external returns ( uint256 ); function add_liquidity ( uint256[] memory _amounts, uint256 _min_mint_amount, address _receiver ) external returns ( uint256 ); function remove_liquidity_one_coin ( uint256 _burn_amount, int128 i, uint256 _min_received ) external returns ( uint256 ); function remove_liquidity_one_coin ( uint256 _burn_amount, int128 i, uint256 _min_received, address _receiver ) external returns ( uint256 ); function remove_liquidity_imbalance ( uint256[] memory _amounts, uint256 _max_burn_amount ) external returns ( uint256 ); function remove_liquidity_imbalance ( uint256[] memory _amounts, uint256 _max_burn_amount, address _receiver ) external returns ( uint256 ); function remove_liquidity ( uint256 _burn_amount, uint256[] memory _min_amounts ) external returns ( uint256[] memory ); function remove_liquidity ( uint256 _burn_amount, uint256[] memory _min_amounts, address _receiver ) external returns ( uint256[] memory ); function remove_liquidity ( uint256 _burn_amount, uint256[] memory _min_amounts, address _receiver, bool _claim_admin_fees ) external returns ( uint256[] memory ); function withdraw_admin_fees ( ) external; function last_price ( uint256 i ) external view returns ( uint256 ); function ema_price ( uint256 i ) external view returns ( uint256 ); function get_p ( uint256 i ) external view returns ( uint256 ); function price_oracle ( uint256 i ) external view returns ( uint256 ); function D_oracle ( ) 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 permit ( address _owner, address _spender, uint256 _value, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external returns ( bool ); function DOMAIN_SEPARATOR ( ) external view returns ( bytes32 ); function get_dx ( int128 i, int128 j, uint256 dy ) external view returns ( uint256 ); function get_dy ( int128 i, int128 j, uint256 dx ) external view returns ( uint256 ); function calc_withdraw_one_coin ( uint256 _burn_amount, int128 i ) external view returns ( uint256 ); function totalSupply ( ) external view returns ( uint256 ); function get_virtual_price ( ) external view returns ( uint256 ); function calc_token_amount ( uint256[] memory _amounts, bool _is_deposit ) external view returns ( uint256 ); function A ( ) external view returns ( uint256 ); function A_precise ( ) external view returns ( uint256 ); function balances ( uint256 i ) external view returns ( uint256 ); function get_balances ( ) external view returns ( uint256[] memory ); function stored_rates ( ) external view returns ( uint256[] memory ); function dynamic_fee ( int128 i, int128 j ) external view returns ( uint256 ); function ramp_A ( uint256 _future_A, uint256 _future_time ) external; function stop_ramp_A ( ) external; function set_new_fee ( uint256 _new_fee, uint256 _new_offpeg_fee_multiplier ) external; function set_ma_exp_time ( uint256 _ma_exp_time, uint256 _D_ma_time ) external; function N_COINS ( ) external view returns ( uint256 ); function coins ( uint256 arg0 ) external view returns ( address ); function fee ( ) external view returns ( uint256 ); function offpeg_fee_multiplier ( ) external view returns ( uint256 ); function admin_fee ( ) external view returns ( uint256 ); 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_balances ( uint256 arg0 ) external view returns ( uint256 ); function ma_exp_time ( ) external view returns ( uint256 ); function D_ma_time ( ) external view returns ( uint256 ); function ma_last_time ( ) external view returns ( uint256 ); function name ( ) external view returns ( string memory ); function symbol ( ) external view returns ( string memory ); function decimals ( ) external view returns ( uint8 ); function version ( ) external view returns ( string memory ); function balanceOf ( address arg0 ) external view returns ( uint256 ); function allowance ( address arg0, address arg1 ) external view returns ( uint256 ); function nonces ( address arg0 ) external view returns ( uint256 ); function salt ( ) external view returns ( bytes32 ); } // 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/I2pool.sol"; // import "../Misc_AMOs/curve/I2poolToken.sol"; // import "../Misc_AMOs/curve/I2poolTokenNoLending.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/Curve/ICurvefrxETHETHPool.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface ICurvefrxETHETHPool { function A() external view returns (uint256); function A_precise() external view returns (uint256); function get_p() external view returns (uint256); function price_oracle() external view returns (uint256); function get_virtual_price() external view returns (uint256); function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) external returns (uint256); function get_dy(int128 i, int128 j, uint256 _dx) external view returns (uint256); function exchange(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external payable returns (uint256); function remove_liquidity(uint256 _amount, uint256[2] memory _min_amounts) external returns (uint256[2] memory); function remove_liquidity_imbalance(uint256[2] memory _amounts, uint256 _max_burn_amount) external returns (uint256); function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 _min_amount) external returns (uint256); function ramp_A(uint256 _future_A, uint256 _future_time) external; function stop_ramp_A() external; function commit_new_fee(uint256 _new_fee, uint256 _new_admin_fee) external; function apply_new_fee() external; function revert_new_parameters() external; function set_ma_exp_time(uint256 _ma_exp_time) external; function commit_transfer_ownership(address _owner) external; function apply_transfer_ownership() external; function revert_transfer_ownership() external; function admin_balances(uint256 i) external view returns (uint256); function withdraw_admin_fees() external; function donate_admin_fees() external; function kill_me() external; function unkill_me() external; function coins(uint256 arg0) external view returns (address); function balances(uint256 arg0) external view returns (uint256); function fee() external view returns (uint256); function admin_fee() external view returns (uint256); function owner() external view returns (address); function lp_token() external view returns (address); function initial_A() external view returns (uint256); function future_A() external view returns (uint256); function initial_A_time() external view returns (uint256); function future_A_time() external view returns (uint256); function admin_actions_deadline() external view returns (uint256); function transfer_ownership_deadline() external view returns (uint256); function future_fee() external view returns (uint256); function future_admin_fee() external view returns (uint256); function future_owner() external view returns (address); function ma_exp_time() external view returns (uint256); function ma_last_time() external view returns (uint256); } // File contracts/Misc_AMOs/convex/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/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/Misc_AMOs/curve/ICurveStableSwapMetaNG.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface ICurveStableSwapMetaNG { function exchange ( int128 i, int128 j, uint256 _dx, uint256 _min_dy ) external returns ( uint256 ); function exchange ( int128 i, int128 j, uint256 _dx, uint256 _min_dy, address _receiver ) external returns ( uint256 ); function exchange_received ( int128 i, int128 j, uint256 _dx, uint256 _min_dy ) external returns ( uint256 ); function exchange_received ( int128 i, int128 j, uint256 _dx, uint256 _min_dy, address _receiver ) external returns ( uint256 ); function exchange_underlying ( int128 i, int128 j, uint256 _dx, uint256 _min_dy ) external returns ( uint256 ); function exchange_underlying ( int128 i, int128 j, uint256 _dx, uint256 _min_dy, address _receiver ) external returns ( uint256 ); function add_liquidity ( uint256[2] memory _amounts, uint256 _min_mint_amount ) external returns ( uint256 ); function add_liquidity ( uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver ) external returns ( uint256 ); function remove_liquidity_one_coin ( uint256 _burn_amount, int128 i, uint256 _min_received ) external returns ( uint256 ); function remove_liquidity_one_coin ( uint256 _burn_amount, int128 i, uint256 _min_received, address _receiver ) external returns ( uint256 ); function remove_liquidity_imbalance ( uint256[2] memory _amounts, uint256 _max_burn_amount ) external returns ( uint256 ); function remove_liquidity_imbalance ( uint256[2] memory _amounts, uint256 _max_burn_amount, address _receiver ) external returns ( uint256 ); function remove_liquidity ( uint256 _burn_amount, uint256[2] memory _min_amounts ) external returns ( uint256[2] memory ); function remove_liquidity ( uint256 _burn_amount, uint256[2] memory _min_amounts, address _receiver ) external returns ( uint256[2] memory ); function remove_liquidity ( uint256 _burn_amount, uint256[2] memory _min_amounts, address _receiver, bool _claim_admin_fees ) external returns ( uint256[2] memory ); function withdraw_admin_fees ( ) external; function last_price ( uint256 i ) external view returns ( uint256 ); function ema_price ( uint256 i ) external view returns ( uint256 ); function get_p ( uint256 i ) external view returns ( uint256 ); function price_oracle ( uint256 i ) external view returns ( uint256 ); function D_oracle ( ) 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 permit ( address _owner, address _spender, uint256 _value, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external returns ( bool ); function DOMAIN_SEPARATOR ( ) external view returns ( bytes32 ); function get_dx ( int128 i, int128 j, uint256 dy ) external view returns ( uint256 ); function get_dx_underlying ( int128 i, int128 j, uint256 dy ) external view returns ( uint256 ); function get_dy ( int128 i, int128 j, uint256 dx ) external view returns ( uint256 ); function get_dy_underlying ( int128 i, int128 j, uint256 dx ) external view returns ( uint256 ); function calc_withdraw_one_coin ( uint256 _burn_amount, int128 i ) external view returns ( uint256 ); function totalSupply ( ) external view returns ( uint256 ); function get_virtual_price ( ) external view returns ( uint256 ); function calc_token_amount ( uint256[2] memory _amounts, bool _is_deposit ) external view returns ( uint256 ); function A ( ) external view returns ( uint256 ); function A_precise ( ) external view returns ( uint256 ); function balances ( uint256 i ) external view returns ( uint256 ); function get_balances ( ) external view returns ( uint256[] memory ); function stored_rates ( ) external view returns ( uint256[] memory ); function dynamic_fee ( int128 i, int128 j ) external view returns ( uint256 ); function ramp_A ( uint256 _future_A, uint256 _future_time ) external; function stop_ramp_A ( ) external; function set_new_fee ( uint256 _new_fee, uint256 _new_offpeg_fee_multiplier ) external; function set_ma_exp_time ( uint256 _ma_exp_time, uint256 _D_ma_time ) external; function N_COINS ( ) external view returns ( uint256 ); function BASE_POOL ( ) external view returns ( address ); function BASE_N_COINS ( ) external view returns ( uint256 ); function BASE_COINS ( uint256 arg0 ) external view returns ( address ); function coins ( uint256 arg0 ) external view returns ( address ); function fee ( ) external view returns ( uint256 ); function offpeg_fee_multiplier ( ) external view returns ( uint256 ); function admin_fee ( ) external view returns ( uint256 ); 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_balances ( uint256 arg0 ) external view returns ( uint256 ); function ma_exp_time ( ) external view returns ( uint256 ); function D_ma_time ( ) external view returns ( uint256 ); function ma_last_time ( ) external view returns ( uint256 ); function name ( ) external view returns ( string memory ); function symbol ( ) external view returns ( string memory ); function decimals ( ) external view returns ( uint8 ); function version ( ) external view returns ( string memory ); function balanceOf ( address arg0 ) external view returns ( uint256 ); function allowance ( address arg0, address arg1 ) external view returns ( uint256 ); function nonces ( address arg0 ) external view returns ( uint256 ); function salt ( ) external view returns ( bytes32 ); } // File contracts/Oracle/AggregatorV3Interface.sol // Original license: SPDX_License_Identifier: MIT interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/Staking/Variants/FraxUnifiedFarm_ERC20_Convex_frxETH.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later contract FraxUnifiedFarm_ERC20_Convex_frxETH is FraxUnifiedFarm_ERC20 { AggregatorV3Interface internal priceFeedETHUSD = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); string public farm_type = "ERC20_Convex_frxETH"; 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 // Most Convex frxETH/XYZ (TOKEN != MINTER / POOL) // stakingToken = IConvexStakingWrapperFrax(_stakingToken); // curveToken = I2poolToken(stakingToken.curveToken()); // curvePool = ICurvefrxETHETHPool(curveToken.minter()); // Some Convex frxETH/XYZ (TOKEN = MINTER / POOL)) // stakingToken = IConvexStakingWrapperFrax(_stakingToken); // curveToken = I2poolToken(stakingToken.curveToken()); // curvePool = ICurvefrxETHETHPool(stakingToken.curveToken()); // Convex frxETH/XYZ NGs (TOKEN = MINTER / POOL)) stakingToken = IConvexStakingWrapperFrax(_stakingToken); curveToken = ICurveStableSwapNG(stakingToken.curveToken()); curvePool = ICurveStableSwapNG(stakingToken.curveToken()); } function getLatestETHPriceE8() public view returns (int) { // Returns in E8 (uint80 roundID, int price, , uint256 updatedAt, uint80 answeredInRound) = priceFeedETHUSD.latestRoundData(); require(price >= 0 && updatedAt!= 0 && answeredInRound >= roundID, "Invalid chainlink price"); return price; } function setETHUSDOracle(address _eth_usd_oracle_address) public onlyByOwnGov { require(_eth_usd_oracle_address != address(0), "Zero address detected"); priceFeedETHUSD = AggregatorV3Interface(_eth_usd_oracle_address); } function fraxPerLPToken() public view override returns (uint256 frax_per_lp_token) { // COMMENTED OUT SO COMPILER DOESNT COMPLAIN. UNCOMMENT WHEN DEPLOYING // Convex frxETH/XYZ // ============================================ { // Assume frxETH = ETH for pricing purposes // Get the USD value of the frxETH per LP token uint256 frxETH_in_pool = IERC20(0x5E8422345238F34275888049021821E8E08CAa1f).balanceOf(address(curvePool)); uint256 frxETH_usd_val_per_lp_e8 = (frxETH_in_pool * uint256(getLatestETHPriceE8())) / curveToken.totalSupply(); frax_per_lp_token = frxETH_usd_val_per_lp_e8 * (1e10); // We use USD as "Frax" here } } }
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 ICurveStableSwapNG","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveToken","outputs":[{"internalType":"contract ICurveStableSwapNG","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":[],"name":"getLatestETHPriceE8","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getProxyFor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getReward","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_extra_too","type":"bool"}],"name":"getReward2","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getRewardExtraLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256[]","name":"rewards_per_duration_arr","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller_addr","type":"address"},{"internalType":"address","name":"reward_token_addr","type":"address"}],"name":"isTokenManagerFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRewardClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"addl_liq","type":"uint256"}],"name":"lockAdditional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"new_ending_ts","type":"uint256"}],"name":"lockLonger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"lockMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_for_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedLiquidityOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedStakes","outputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOf","outputs":[{"components":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"internalType":"struct FraxUnifiedFarm_ERC20.LockedStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOfLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"maxLPForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"minVeFXSForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"minVeFXSForMaxBoostProxy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"proxyStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"}],"name":"proxyToggleStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxy_lp_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token_idx","type":"uint256"}],"name":"rewardRates","outputs":[{"internalType":"uint256","name":"rwd_rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint256[]","name":"newRewardsPerTokenStored","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_eth_usd_oracle_address","type":"address"}],"name":"setETHUSDOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[6]","name":"_misc_vars","type":"uint256[6]"}],"name":"setMiscVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalsPaused","type":"bool"},{"internalType":"bool","name":"_rewardsCollectionPaused","type":"bool"},{"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
671bc16d674ec8000060068190556305a39a806007556001600855673782dace9d9000006009819055600a91909155600b5560c06040526005608090815264189718171b60d91b60a0526023906200005890826200071c565b50602880546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b841917905560408051808201909152601381527f45524332305f436f6e7665785f667278455448000000000000000000000000006020820152602990620000c290826200071c565b50348015620000d057600080fd5b506040516200625a3803806200625a833981016040819052620000f39162000944565b86868686868686868686868686856001600160a01b0381166200015c5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15060016002558451620001ce906010906020880190620005b6565b508151620001e4906011906020850190620005b6565b508051620001fa906012906020840190620005b6565b5082516200021090601390602086019062000620565b5060005b8551811015620003c457806015600088848151811062000238576200023862000a4b565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506001601460008884815181106200027f576200027f62000a4b565b6020908102919091018101516001600160a01b031682528101919091526040016000908120805460ff191692151592909217909155601680546001810182559082527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901558451859082908110620002fb57620002fb62000a4b565b6020026020010151600f60008884815181106200031c576200031c62000a4b565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601a805460018181019092557f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01829055601b805480830182559083527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc101919091550162000214565b506022805460ff19169055426005556040805163513872bd60e01b81529051733669c421b77340b2979d1a00a792cc2ee0fce7379163513872bd9160048083019260209291908290030181865afa15801562000424573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200044a919062000a61565b6004819055505050505050505050505050505080602460016101000a8154816001600160a01b0302191690836001600160a01b03160217905550602460019054906101000a90046001600160a01b03166001600160a01b0316634f39059c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004fe919062000a7b565b602580546001600160a01b0319166001600160a01b03928316179055602454604080516313ce416760e21b8152905161010090920490921691634f39059c9160048083019260209291908290030181865afa15801562000562573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000588919062000a7b565b602680546001600160a01b0319166001600160a01b03929092169190911790555062000aa095505050505050565b8280548282559060005260206000209081019282156200060e579160200282015b828111156200060e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620005d7565b506200061c9291506200065e565b5090565b8280548282559060005260206000209081019282156200060e579160200282015b828111156200060e57825182559160200191906001019062000641565b5b808211156200061c57600081556001016200065f565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620006a057607f821691505b602082108103620006c157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000717576000816000526020600020601f850160051c81016020861015620006f25750805b601f850160051c820191505b818110156200071357828155600101620006fe565b5050505b505050565b81516001600160401b0381111562000738576200073862000675565b62000750816200074984546200068b565b84620006c7565b602080601f8311600181146200078857600084156200076f5750858301515b600019600386901b1c1916600185901b17855562000713565b600085815260208120601f198616915b82811015620007b95788860151825594840194600190910190840162000798565b5085821015620007d85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200080057600080fd5b919050565b604051601f8201601f191681016001600160401b038111828210171562000830576200083062000675565b604052919050565b60006001600160401b0382111562000854576200085462000675565b5060051b60200190565b600082601f8301126200087057600080fd5b8151602062000889620008838362000838565b62000805565b8083825260208201915060208460051b870101935086841115620008ac57600080fd5b602086015b84811015620008d357620008c581620007e8565b8352918301918301620008b1565b509695505050505050565b600082601f830112620008f057600080fd5b8151602062000903620008838362000838565b8083825260208201915060208460051b8701019350868411156200092657600080fd5b602086015b84811015620008d357805183529183019183016200092b565b600080600080600080600060e0888a0312156200096057600080fd5b6200096b88620007e8565b60208901519097506001600160401b03808211156200098957600080fd5b620009978b838c016200085e565b975060408a0151915080821115620009ae57600080fd5b620009bc8b838c016200085e565b965060608a0151915080821115620009d357600080fd5b620009e18b838c01620008de565b955060808a0151915080821115620009f857600080fd5b62000a068b838c016200085e565b945060a08a015191508082111562000a1d57600080fd5b5062000a2c8a828b016200085e565b92505062000a3d60c08901620007e8565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a7457600080fd5b5051919050565b60006020828403121562000a8e57600080fd5b62000a9982620007e8565b9392505050565b6157aa8062000ab06000396000f3fe608060405234801561001057600080fd5b50600436106104715760003560e01c80637d6ef08e11610250578063cdc82e8011610150578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a6f578063facefb6414610a82578063fff6cae914610a9557600080fd5b8063f2a8d34914610a53578063f2caeb1e14610a5c57600080fd5b8063e1ba95d214610a26578063e7f3058214610a2e578063ebe2b12b14610a41578063f288baf614610a4a57600080fd5b8063d5e1a9c61161011f578063d9f96e8d11610104578063d9f96e8d146109d5578063de1a655114610a0b578063e01f62bf14610a1e57600080fd5b8063d5e1a9c6146109af578063d7400d56146109c257600080fd5b8063cdc82e8014610977578063d2010fb414610980578063d2fbdc0d14610989578063d42fc9b41461099c57600080fd5b8063a0f23476116101e3578063bdb123e3116101b2578063c354382611610197578063c354382614610925578063c8f33c9114610938578063ca6df29d1461094157600080fd5b8063bdb123e31461090a578063c00007b01461091257600080fd5b8063a0f23476146108d2578063aa1d4fce146108e5578063b85efd06146108ee578063b94c4dcb1461090157600080fd5b80638bad86a71161021f5780638bad86a7146108645780638da5cb5b1461089257806391cf600a146108b25780639637927f146108c557600080fd5b80637d6ef08e1461080a5780637f472e54146108295780638980f11f1461083c57806389b5f00b1461084f57600080fd5b806341a16f3f116103765780636c430dbb116102ee578063741d3c18116102bd5780637910d17b116102a25780637910d17b146107b45780637970833e146107c757806379ba50971461080257600080fd5b8063741d3c181461078e578063774d4ae7146107a157600080fd5b80636c430dbb146107385780636e27cef91461075857806370641a361461076157806372f702f31461076957600080fd5b806353a47bb7116103455780635bfd92581161032a5780635bfd92581461070857806364f2c06014610710578063693392451461071857600080fd5b806353a47bb7146106e057806354fd4d501461070057600080fd5b806341a16f3f1461066257806341edbdf0146106985780634f39059c146106ad5780634fd2b536146106cd57600080fd5b80631face856116104095780632c0c2a0a116103d857806336f89af2116103bd57806336f89af21461060f578063386a952514610645578063387edc861461064f57600080fd5b80632c0c2a0a146105e95780632df079f1146105fc57600080fd5b80631face85614610538578063218751b21461054b578063231b68dc1461059057806328408bab146105b357600080fd5b80631627540c116104455780631627540c146104e857806317b18c89146104fd5780631c1f78eb146105105780631e090f011461051857600080fd5b80628cc262146104765780630238b9361461049f5780630d7bac4f146104c057806312edb24c146104d3575b600080fd5b61048961048436600461512a565b610a9d565b6040516104969190615145565b60405180910390f35b6104b26104ad366004615197565b610c12565b604051908152602001610496565b6104b26104ce3660046151d7565b610d13565b6104db610d3f565b60405161049691906151f0565b6104fb6104f636600461512a565b610dae565b005b6104b261050b36600461523e565b610ece565b610489610f58565b61052b61052636600461512a565b610fef565b6040516104969190615260565b6104b261054636600461512a565b6110a3565b60265461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610496565b6105a361059e3660046152ce565b6110e8565b6040519015158152602001610496565b61056b6105c136600461512a565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104b26105f736600461512a565b6111ce565b6104fb61060a366004615301565b6114ba565b6104b261061d36600461512a565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b6104b262093a8081565b6104fb61065d36600461512a565b611633565b61056b61067036600461512a565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6106a0611792565b6040516104969190615381565b60255461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26106db36600461512a565b611820565b60015461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6106a0611841565b6104b261184e565b601d546104b2565b6104b261072636600461512a565b60156020526000908152604090205481565b6104b261074636600461512a565b60196020526000908152604090205481565b6104b260085481565b6104896119c2565b60245461056b90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6104fb61079c36600461512a565b611b17565b6104b26107af3660046153d2565b611c7a565b6104896107c23660046153fc565b611e86565b6107da6107d53660046153d2565b611f02565b604080519586526020860194909452928401919091526060830152608082015260a001610496565b6104fb611f50565b6104b261081836600461512a565b602080526000908152604090205481565b6104b261083736600461512a565b61209b565b6104fb61084a3660046153d2565b6120b2565b6022546105a390640100000000900460ff1681565b61087761087236600461512a565b612243565b60408051938452602084019290925290820152606001610496565b60005461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104fb6108c036600461512a565b612470565b6022546105a39060ff1681565b6104b26108e036600461512a565b612563565b6104b260095481565b6104fb6108fc36600461523e565b61262d565b6104b260075481565b6104b26128c9565b61048961092036600461512a565b612a0e565b61056b61093336600461512a565b612a96565b6104b260055481565b6104b261094f36600461512a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b6104b260065481565b6104b260035481565b6104fb61099736600461523e565b612af9565b6104b26109aa36600461512a565b612f46565b6104fb6109bd366004615433565b612f82565b6104fb6109d036600461512a565b613171565b6104b26109e336600461512a565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104fb610a193660046152ce565b61338b565b601c546104b2565b6104fb613472565b6104fb610a3c36600461512a565b613543565b6104b260045481565b6104b2600a5481565b6104b2600b5481565b6104b2610a6a3660046151d7565b6136a3565b6104fb610a7d366004615480565b6137ba565b6104fb610a903660046154cc565b613986565b6104fb613b46565b60606000610aa96119c2565b60105490915067ffffffffffffffff811115610ac757610ac761549d565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610c0c5760005b601054811015610c0a5773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610b8f57610b8f615571565b6020026020010151610ba191906155cf565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610bd191906155e2565b610bdb91906155f9565b610be59190615634565b838281518110610bf757610bf7615571565b6020908102919091010152600101610b22565b505b50919050565b60006002805403610c84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610c7b565b610d0633848685613beb565b6001600255949350505050565b600654600754600091610d3991610d2a82866155e2565b610d3491906155f9565b613daa565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610da457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d79575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610c7b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610f3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055610f4c3380858542613dc2565b60016002559392505050565b60135460609067ffffffffffffffff811115610f7657610f7661549d565b604051908082528060200260200182016040528015610f9f578160200160208202803683370190505b50905060005b601354811015610feb5762093a80610fbc826136a3565b610fc691906155e2565b828281518110610fd857610fd8615571565b6020908102919091010152600101610fa5565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561109857838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190611034565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a7640000916110de916155e2565b610d3991906155f9565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff1661111d57506000610d39565b73ffffffffffffffffffffffffffffffffffffffff83161580611154575073ffffffffffffffffffffffffffffffffffffffff8216155b1561116157506000610d39565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361118c57506001610d39565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f60205260409020548185169116036111c557506001610d39565b50600092915050565b600080806111db84612a96565b905073ffffffffffffffffffffffffffffffffffffffff8116156112a0576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611277573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129b9190615647565b611342565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa15801561131e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113429190615647565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d29190615647565b6113dc91906155e2565b600954600a546113ec90866155e2565b6113f691906155e2565b61140091906155f9565b905060008073ffffffffffffffffffffffffffffffffffffffff84161561142f5761142a8461209b565b611438565b61143887611820565b9050801561148a57600081611455670de0b6b3a7640000886155e2565b61145f91906155f9565b9050670de0b6b3a7640000600a548261147891906155e2565b61148291906155f9565b92505061148f565b600091505b5080821161149d578061149f565b815b9450600a548511156114b157600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114f35750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115f85750602254640100000000900460ff16155b1561162d57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b600280540361169e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055602254640100000000900460ff1615611717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b60225462010000900460ff161561178a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c7b565b506001600255565b6029805461179f90615660565b80601f01602080910402602001604051908101604052809291908181526020018280546117cb90615660565b80156118185780601f106117ed57610100808354040283529160200191611818565b820191906000526020600020905b8154815290600101906020018083116117fb57829003601f168201915b505050505081565b6000670de0b6b3a7640000600b5461183784612f46565b6110de91906155e2565b6023805461179f90615660565b6026546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526000908190735e8422345238f34275888049021821e8e08caa1f906370a0823190602401602060405180830381865afa1580156118d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f99190615647565b90506000602560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561196a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198e9190615647565b6119966128c9565b6119a090846155e2565b6119aa91906155f9565b90506119bb816402540be4006155e2565b9250505090565b6060601c54600014806119d55750601d54155b15611a2f576016805480602002602001604051908101604052809291908181526020018280548015610da457602002820191906000526020600020905b815481526020019060010190808311611a12575050505050905090565b60105467ffffffffffffffff811115611a4a57611a4a61549d565b604051908082528060200260200182016040528015611a73578160200160208202803683370190505b50905060005b601654811015610feb57601d54611a8f826136a3565b600554611a9a614186565b611aa491906155cf565b611aae91906155e2565b611ac090670de0b6b3a76400006155e2565b611aca91906155f9565b60168281548110611add57611add615571565b9060005260206000200154611af29190615634565b828281518110611b0457611b04615571565b6020908102919091010152600101611a79565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611b505750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611bb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff8116611c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610c7b565b602880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611cb457611cb4615571565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611d3257506020810151611d5a565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611e1a57606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611e11576000818360600151611da891906155cf565b90506000836060015142611dbc91906155cf565b90506000611dce6104ce6002856155f9565b90506000611ddc83826155e2565b611de685846155e2565b611df09190615634565b9050611dfc8385615634565b611e0690826155f9565b965050505050611e6a565b60009250611e6a565b600080828460600151611e2d91906155cf565b90506000428560600151611e4191906155cf565b90506002611e4f8284615634565b611e5991906155f9565b92505050611e6681610d13565b9350505b8160800151831115611e7e57816080015192505b505092915050565b60606002805403611ef3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055610f4c338484614199565b60276020528160005260406000208181548110611f1e57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ff7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610c7b565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b54611837846110a3565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806120df57506120df33826110e8565b612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff168080156121a1575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b806121cc5750801580156121cc575060005473ffffffffffffffffffffffffffffffffffffffff1633145b156121dc5761162d8433856144d2565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610c7b565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080612274846111ce565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040812054919350901580156122ce575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b806122fe575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b1561230a57508161234a565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090205460029061233d9085615634565b61234791906155f9565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156124675773ffffffffffffffffffffffffffffffffffffffff861660009081526027602052604081208054839081106123b5576123b5615571565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600061240e8884611c7a565b60408301519091506000670de0b6b3a764000061242b8785615634565b61243590846155e2565b61243f91906155f9565b6124499083615634565b90506124558188615634565b96505060019093019250612351915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806124a95750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61250f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461257591906155e2565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156125ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126239190615647565b61183791906155e2565b6002805403612698576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b600280556022546301000000900460ff1615612710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b602254640100000000900460ff1615612785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b61279133336001614199565b5060008061279f3385614642565b9150915060008383604001516127b59190615634565b90506024546127e190610100900473ffffffffffffffffffffffffffffffffffffffff16333087614810565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260279091529190912080548490811061283357612833615571565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612882338560016149ae565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561293e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296291906156c7565b9450945050935093506000831215801561297b57508115155b801561299f57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b612a05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610c7b565b50909392505050565b60606002805403612a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055612a8b33836001614199565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612ac8575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b600280556022546301000000900460ff1615612bdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b602254640100000000900460ff1615612c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b612c5d33336001614199565b50600080612c6b3385614642565b91509150428311612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610c7b565b600042836060015111612cec576000612cfc565b428360600151612cfc91906155cf565b90506000612d0a42866155cf565b9050818111612d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610c7b565b600854811015612de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c7b565b600754811115612e4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c7b565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612e7d83610d13565b9052336000908152602760205260409020805485908110612ea057612ea0615571565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612ef03360006001614b1d565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a7640000916110de916155e2565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612faf5750612faf33826110e8565b613015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff851660009081526015602052604090205460138054869290811061305057613050615571565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481106130b1576130b1615571565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94851617905591871681526015909152604090205460128054849290811061312257613122615571565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16613200576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff1661329a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610c7b565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff16801561330e57336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff8516845291805282208054919290916133089084906155cf565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091613382908490615634565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806133b857506133b833826110e8565b61341e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314806134ab5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff166135bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c7b565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036136a05773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161369a9084906155cf565b90915550505b50565b600080601183815481106136b9576136b9615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561379457670de0b6b3a7640000601a84815481106136ff576136ff615571565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137799190615647565b61378391906155e2565b61378d91906155f9565b9150610c0c565b601383815481106137a7576137a7615571565b9060005260206000200154915050919050565b60005b601154811015613982576000601182815481106137dc576137dc615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561397957828061382e5750601b828154811061382057613820615571565b906000526020600020015442115b15613979576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af11580156138a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138c99190615647565b601a83815481106138dc576138dc615571565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139599190615647565b601b838154811061396c5761396c615571565b6000918252602090912001555b506001016137bd565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806139bf5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613a25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b8051670de0b6b3a76400001115613a98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610c7b565b6080810151600111801590613ab2575060a0810151600111155b613b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610c7b565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff1615613bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b613bc560006137ba565b613bcd61184e565b6003556004544210613be357613be1614c9c565b565b613be1614fb1565b602254600090640100000000900460ff16613c0e57613c0c85856001614199565b505b600080613c1b8786614642565b91509150816060015142101580613c39575060225460ff1615156001145b613c9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610c7b565b60408201518015613d9f57602454613cd390610100900473ffffffffffffffffffffffffffffffffffffffff1688836144d2565b73ffffffffffffffffffffffffffffffffffffffff88166000908152602760205260409020805483908110613d0a57613d0a615571565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613d4490899083906149ae565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b6000818310613db95781613dbb565b825b9392505050565b6000856001613dd382826000614b1d565b602254640100000000900460ff1615613e48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b6022546301000000900460ff1615613ebc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b600854851015613f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c7b565b600754851115613f94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c7b565b602454613fbe90610100900473ffffffffffffffffffffffffffffffffffffffff16883089614810565b6000613fc986610d13565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b905290925090606081016140bc8a8a615634565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155614118908b908a906149ae565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b600061419442600454613daa565b905090565b60608360016141aa82826000614b1d565b602254640100000000900460ff161561421f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b60225462010000900460ff1615614292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff8111156142d5576142d561549d565b6040519080825280602002602001820160405280156142fe578160200160208202803683370190505b50925060005b6010548110156144c85773ffffffffffffffffffffffffffffffffffffffff87166000908152601860209081526040808320848452909152902054845185908390811061435357614353615571565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8816600090815260188252604080822084835290925290812081905584518590839081106143a7576143a7615571565b602002602001015111156144c057614416601082815481106143cb576143cb615571565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061440957614409615571565b60200260200101516144d2565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061446057614460615571565b60200260200101516010848154811061447b5761447b615571565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101614304565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916145699190615717565b6000604051808303816000865af19150503d80600081146145a6576040519150601f19603f3d011682016040523d82523d6000602084013e6145ab565b606091505b50915091508180156145d55750805115806145d55750808060200190518101906145d59190615733565b61463b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610c7b565b5050505050565b6146776040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156147945760005b73ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020548110156147925773ffffffffffffffffffffffffffffffffffffffff851660009081526027602052604090208054829081106146e6576146e6615571565b906000526020600020906005020160000154840361478a5773ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902080548290811061473557614735615571565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614792565b600101614682565b505b82158015906147a35750815183145b614809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610c7b565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916148af9190615717565b6000604051808303816000865af19150503d80600081146148ec576040519150601f19603f3d011682016040523d82523d6000602084013e6148f1565b606091505b509150915081801561491b57508051158061491b57508080602001905181019061491b9190615733565b6149a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610c7b565b505050505050565b60006149b984612a96565b90508115614a6d5782601c60008282546149d39190615634565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604081208054859290614a0d908490615634565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614a685773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614a62908490615634565b90915550505b614b14565b82601c6000828254614a7f91906155cf565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604081208054859290614ab99084906155cf565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614b145773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614b0e9084906155cf565b90915550505b61162d84600060015b602254640100000000900460ff16614b3d578115614b3d57614b3d613b46565b8015614b7357614b4c836111ce565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff83161561223e576000806000614b9d86612243565b6022549295509093509150640100000000900460ff16614bc057614bc08661501a565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c60205260409020829055828110614c44576000614bfb84836155cf565b905080601d54614c0b9190615634565b601d55614c188185615634565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f6020526040902055506149a6565b6000614c5082856155cf565b905080601d54614c6091906155cf565b601d55614c6d81856155cf565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614ca4614fb1565b60005b601254811015614d8b57600060128281548110614cc657614cc6615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614d82576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614d5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d7f9190615750565b50505b50600101614ca7565b50600062093a8060045442614da091906155cf565b614daa91906155f9565b905060005b601054811015614f835760108181548110614dcc57614dcc615571565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e679190615647565b614e72836001615634565b62093a80614e7f846136a3565b614e8991906155e2565b614e9391906155e2565b111560108281548110614ea857614ea8615571565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614f7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7b9190615381565b50600101614daf565b5062093a80614f93826001615634565b614f9d91906155e2565b600454614faa9190615634565b6004556136a05b6000614fbb6119c2565b905060005b60165481101561500b57818181518110614fdc57614fdc615571565b602002602001015160168281548110614ff757614ff7615571565b600091825260209091200155600101614fc0565b50615014614186565b60055550565b73ffffffffffffffffffffffffffffffffffffffff8116156136a057600061504182610a9d565b905060005b81518110156150a55781818151811061506157615061615571565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101615046565b5060005b815181101561223e57601681815481106150c5576150c5615571565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff861683526017825260408084208585529092529120556001016150a9565b803573ffffffffffffffffffffffffffffffffffffffff81168114612af457600080fd5b60006020828403121561513c57600080fd5b613dbb82615106565b6020808252825182820181905260009190848201906040850190845b8181101561517d57835183529284019291840191600101615161565b50909695505050505050565b80151581146136a057600080fd5b6000806000606084860312156151ac57600080fd5b833592506151bc60208501615106565b915060408401356151cc81615189565b809150509250925092565b6000602082840312156151e957600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561517d57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161520c565b6000806040838503121561525157600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b828110156152c15781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a0909301929085019060010161527d565b5091979650505050505050565b600080604083850312156152e157600080fd5b6152ea83615106565b91506152f860208401615106565b90509250929050565b6000806000806080858703121561531757600080fd5b843561532281615189565b9350602085013561533281615189565b9250604085013561534281615189565b9150606085013561535281615189565b939692955090935050565b60005b83811015615378578181015183820152602001615360565b50506000910152565b60208152600082518060208401526153a081604085016020870161535d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156153e557600080fd5b6153ee83615106565b946020939093013593505050565b6000806040838503121561540f57600080fd5b61541883615106565b9150602083013561542881615189565b809150509250929050565b6000806000806080858703121561544957600080fd5b61545285615106565b93506020850135925061546760408601615106565b915061547560608601615106565b905092959194509250565b60006020828403121561549257600080fd5b8135613dbb81615189565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c082840312156154de57600080fd5b82601f8301126154ed57600080fd5b60405160c0810181811067ffffffffffffffff82111715615537577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561554c57600080fd5b845b8181101561556657803583526020928301920161554e565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610d3957610d396155a0565b8082028115828204841417610d3957610d396155a0565b60008261562f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610d3957610d396155a0565b60006020828403121561565957600080fd5b5051919050565b600181811c9082168061567457607f821691505b602082108103610c0c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b805169ffffffffffffffffffff81168114612af457600080fd5b600080600080600060a086880312156156df57600080fd5b6156e8866156ad565b945060208601519350604086015192506060860151915061570b608087016156ad565b90509295509295909350565b6000825161572981846020870161535d565b9190910192915050565b60006020828403121561574557600080fd5b8151613dbb81615189565b6000806040838503121561576357600080fd5b50508051602090910151909290915056fea26469706673582212201094739c3c5858a4971e25d652206dbcc4add942108dc3182acb57123271e4cc64736f6c63430008170033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000d893522d2ccd40ea6c1414815e3ead1b58a83d5100000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104715760003560e01c80637d6ef08e11610250578063cdc82e8011610150578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a6f578063facefb6414610a82578063fff6cae914610a9557600080fd5b8063f2a8d34914610a53578063f2caeb1e14610a5c57600080fd5b8063e1ba95d214610a26578063e7f3058214610a2e578063ebe2b12b14610a41578063f288baf614610a4a57600080fd5b8063d5e1a9c61161011f578063d9f96e8d11610104578063d9f96e8d146109d5578063de1a655114610a0b578063e01f62bf14610a1e57600080fd5b8063d5e1a9c6146109af578063d7400d56146109c257600080fd5b8063cdc82e8014610977578063d2010fb414610980578063d2fbdc0d14610989578063d42fc9b41461099c57600080fd5b8063a0f23476116101e3578063bdb123e3116101b2578063c354382611610197578063c354382614610925578063c8f33c9114610938578063ca6df29d1461094157600080fd5b8063bdb123e31461090a578063c00007b01461091257600080fd5b8063a0f23476146108d2578063aa1d4fce146108e5578063b85efd06146108ee578063b94c4dcb1461090157600080fd5b80638bad86a71161021f5780638bad86a7146108645780638da5cb5b1461089257806391cf600a146108b25780639637927f146108c557600080fd5b80637d6ef08e1461080a5780637f472e54146108295780638980f11f1461083c57806389b5f00b1461084f57600080fd5b806341a16f3f116103765780636c430dbb116102ee578063741d3c18116102bd5780637910d17b116102a25780637910d17b146107b45780637970833e146107c757806379ba50971461080257600080fd5b8063741d3c181461078e578063774d4ae7146107a157600080fd5b80636c430dbb146107385780636e27cef91461075857806370641a361461076157806372f702f31461076957600080fd5b806353a47bb7116103455780635bfd92581161032a5780635bfd92581461070857806364f2c06014610710578063693392451461071857600080fd5b806353a47bb7146106e057806354fd4d501461070057600080fd5b806341a16f3f1461066257806341edbdf0146106985780634f39059c146106ad5780634fd2b536146106cd57600080fd5b80631face856116104095780632c0c2a0a116103d857806336f89af2116103bd57806336f89af21461060f578063386a952514610645578063387edc861461064f57600080fd5b80632c0c2a0a146105e95780632df079f1146105fc57600080fd5b80631face85614610538578063218751b21461054b578063231b68dc1461059057806328408bab146105b357600080fd5b80631627540c116104455780631627540c146104e857806317b18c89146104fd5780631c1f78eb146105105780631e090f011461051857600080fd5b80628cc262146104765780630238b9361461049f5780630d7bac4f146104c057806312edb24c146104d3575b600080fd5b61048961048436600461512a565b610a9d565b6040516104969190615145565b60405180910390f35b6104b26104ad366004615197565b610c12565b604051908152602001610496565b6104b26104ce3660046151d7565b610d13565b6104db610d3f565b60405161049691906151f0565b6104fb6104f636600461512a565b610dae565b005b6104b261050b36600461523e565b610ece565b610489610f58565b61052b61052636600461512a565b610fef565b6040516104969190615260565b6104b261054636600461512a565b6110a3565b60265461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610496565b6105a361059e3660046152ce565b6110e8565b6040519015158152602001610496565b61056b6105c136600461512a565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104b26105f736600461512a565b6111ce565b6104fb61060a366004615301565b6114ba565b6104b261061d36600461512a565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b6104b262093a8081565b6104fb61065d36600461512a565b611633565b61056b61067036600461512a565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6106a0611792565b6040516104969190615381565b60255461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26106db36600461512a565b611820565b60015461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6106a0611841565b6104b261184e565b601d546104b2565b6104b261072636600461512a565b60156020526000908152604090205481565b6104b261074636600461512a565b60196020526000908152604090205481565b6104b260085481565b6104896119c2565b60245461056b90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6104fb61079c36600461512a565b611b17565b6104b26107af3660046153d2565b611c7a565b6104896107c23660046153fc565b611e86565b6107da6107d53660046153d2565b611f02565b604080519586526020860194909452928401919091526060830152608082015260a001610496565b6104fb611f50565b6104b261081836600461512a565b602080526000908152604090205481565b6104b261083736600461512a565b61209b565b6104fb61084a3660046153d2565b6120b2565b6022546105a390640100000000900460ff1681565b61087761087236600461512a565b612243565b60408051938452602084019290925290820152606001610496565b60005461056b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104fb6108c036600461512a565b612470565b6022546105a39060ff1681565b6104b26108e036600461512a565b612563565b6104b260095481565b6104fb6108fc36600461523e565b61262d565b6104b260075481565b6104b26128c9565b61048961092036600461512a565b612a0e565b61056b61093336600461512a565b612a96565b6104b260055481565b6104b261094f36600461512a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b6104b260065481565b6104b260035481565b6104fb61099736600461523e565b612af9565b6104b26109aa36600461512a565b612f46565b6104fb6109bd366004615433565b612f82565b6104fb6109d036600461512a565b613171565b6104b26109e336600461512a565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104fb610a193660046152ce565b61338b565b601c546104b2565b6104fb613472565b6104fb610a3c36600461512a565b613543565b6104b260045481565b6104b2600a5481565b6104b2600b5481565b6104b2610a6a3660046151d7565b6136a3565b6104fb610a7d366004615480565b6137ba565b6104fb610a903660046154cc565b613986565b6104fb613b46565b60606000610aa96119c2565b60105490915067ffffffffffffffff811115610ac757610ac761549d565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610c0c5760005b601054811015610c0a5773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610b8f57610b8f615571565b6020026020010151610ba191906155cf565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610bd191906155e2565b610bdb91906155f9565b610be59190615634565b838281518110610bf757610bf7615571565b6020908102919091010152600101610b22565b505b50919050565b60006002805403610c84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610c7b565b610d0633848685613beb565b6001600255949350505050565b600654600754600091610d3991610d2a82866155e2565b610d3491906155f9565b613daa565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610da457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d79575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610c7b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610f3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055610f4c3380858542613dc2565b60016002559392505050565b60135460609067ffffffffffffffff811115610f7657610f7661549d565b604051908082528060200260200182016040528015610f9f578160200160208202803683370190505b50905060005b601354811015610feb5762093a80610fbc826136a3565b610fc691906155e2565b828281518110610fd857610fd8615571565b6020908102919091010152600101610fa5565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561109857838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190611034565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a7640000916110de916155e2565b610d3991906155f9565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff1661111d57506000610d39565b73ffffffffffffffffffffffffffffffffffffffff83161580611154575073ffffffffffffffffffffffffffffffffffffffff8216155b1561116157506000610d39565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361118c57506001610d39565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f60205260409020548185169116036111c557506001610d39565b50600092915050565b600080806111db84612a96565b905073ffffffffffffffffffffffffffffffffffffffff8116156112a0576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611277573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129b9190615647565b611342565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa15801561131e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113429190615647565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d29190615647565b6113dc91906155e2565b600954600a546113ec90866155e2565b6113f691906155e2565b61140091906155f9565b905060008073ffffffffffffffffffffffffffffffffffffffff84161561142f5761142a8461209b565b611438565b61143887611820565b9050801561148a57600081611455670de0b6b3a7640000886155e2565b61145f91906155f9565b9050670de0b6b3a7640000600a548261147891906155e2565b61148291906155f9565b92505061148f565b600091505b5080821161149d578061149f565b815b9450600a548511156114b157600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114f35750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115f85750602254640100000000900460ff16155b1561162d57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b600280540361169e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055602254640100000000900460ff1615611717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b60225462010000900460ff161561178a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c7b565b506001600255565b6029805461179f90615660565b80601f01602080910402602001604051908101604052809291908181526020018280546117cb90615660565b80156118185780601f106117ed57610100808354040283529160200191611818565b820191906000526020600020905b8154815290600101906020018083116117fb57829003601f168201915b505050505081565b6000670de0b6b3a7640000600b5461183784612f46565b6110de91906155e2565b6023805461179f90615660565b6026546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526000908190735e8422345238f34275888049021821e8e08caa1f906370a0823190602401602060405180830381865afa1580156118d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f99190615647565b90506000602560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561196a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198e9190615647565b6119966128c9565b6119a090846155e2565b6119aa91906155f9565b90506119bb816402540be4006155e2565b9250505090565b6060601c54600014806119d55750601d54155b15611a2f576016805480602002602001604051908101604052809291908181526020018280548015610da457602002820191906000526020600020905b815481526020019060010190808311611a12575050505050905090565b60105467ffffffffffffffff811115611a4a57611a4a61549d565b604051908082528060200260200182016040528015611a73578160200160208202803683370190505b50905060005b601654811015610feb57601d54611a8f826136a3565b600554611a9a614186565b611aa491906155cf565b611aae91906155e2565b611ac090670de0b6b3a76400006155e2565b611aca91906155f9565b60168281548110611add57611add615571565b9060005260206000200154611af29190615634565b828281518110611b0457611b04615571565b6020908102919091010152600101611a79565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611b505750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611bb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff8116611c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610c7b565b602880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611cb457611cb4615571565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611d3257506020810151611d5a565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611e1a57606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611e11576000818360600151611da891906155cf565b90506000836060015142611dbc91906155cf565b90506000611dce6104ce6002856155f9565b90506000611ddc83826155e2565b611de685846155e2565b611df09190615634565b9050611dfc8385615634565b611e0690826155f9565b965050505050611e6a565b60009250611e6a565b600080828460600151611e2d91906155cf565b90506000428560600151611e4191906155cf565b90506002611e4f8284615634565b611e5991906155f9565b92505050611e6681610d13565b9350505b8160800151831115611e7e57816080015192505b505092915050565b60606002805403611ef3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055610f4c338484614199565b60276020528160005260406000208181548110611f1e57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ff7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610c7b565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b54611837846110a3565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806120df57506120df33826110e8565b612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff168080156121a1575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b806121cc5750801580156121cc575060005473ffffffffffffffffffffffffffffffffffffffff1633145b156121dc5761162d8433856144d2565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610c7b565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080612274846111ce565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040812054919350901580156122ce575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b806122fe575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b1561230a57508161234a565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090205460029061233d9085615634565b61234791906155f9565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156124675773ffffffffffffffffffffffffffffffffffffffff861660009081526027602052604081208054839081106123b5576123b5615571565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600061240e8884611c7a565b60408301519091506000670de0b6b3a764000061242b8785615634565b61243590846155e2565b61243f91906155f9565b6124499083615634565b90506124558188615634565b96505060019093019250612351915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806124a95750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61250f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461257591906155e2565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156125ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126239190615647565b61183791906155e2565b6002805403612698576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b600280556022546301000000900460ff1615612710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b602254640100000000900460ff1615612785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b61279133336001614199565b5060008061279f3385614642565b9150915060008383604001516127b59190615634565b90506024546127e190610100900473ffffffffffffffffffffffffffffffffffffffff16333087614810565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260279091529190912080548490811061283357612833615571565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612882338560016149ae565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561293e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296291906156c7565b9450945050935093506000831215801561297b57508115155b801561299f57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b612a05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610c7b565b50909392505050565b60606002805403612a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b60028055612a8b33836001614199565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612ac8575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c7b565b600280556022546301000000900460ff1615612bdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b602254640100000000900460ff1615612c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b612c5d33336001614199565b50600080612c6b3385614642565b91509150428311612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610c7b565b600042836060015111612cec576000612cfc565b428360600151612cfc91906155cf565b90506000612d0a42866155cf565b9050818111612d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610c7b565b600854811015612de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c7b565b600754811115612e4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c7b565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612e7d83610d13565b9052336000908152602760205260409020805485908110612ea057612ea0615571565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612ef03360006001614b1d565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a7640000916110de916155e2565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612faf5750612faf33826110e8565b613015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff851660009081526015602052604090205460138054869290811061305057613050615571565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481106130b1576130b1615571565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94851617905591871681526015909152604090205460128054849290811061312257613122615571565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16613200576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff1661329a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610c7b565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff16801561330e57336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff8516845291805282208054919290916133089084906155cf565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091613382908490615634565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806133b857506133b833826110e8565b61341e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610c7b565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314806134ab5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff166135bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610c7b565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036136a05773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161369a9084906155cf565b90915550505b50565b600080601183815481106136b9576136b9615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561379457670de0b6b3a7640000601a84815481106136ff576136ff615571565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137799190615647565b61378391906155e2565b61378d91906155f9565b9150610c0c565b601383815481106137a7576137a7615571565b9060005260206000200154915050919050565b60005b601154811015613982576000601182815481106137dc576137dc615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561397957828061382e5750601b828154811061382057613820615571565b906000526020600020015442115b15613979576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af11580156138a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138c99190615647565b601a83815481106138dc576138dc615571565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139599190615647565b601b838154811061396c5761396c615571565b6000918252602090912001555b506001016137bd565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806139bf5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613a25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610c7b565b8051670de0b6b3a76400001115613a98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610c7b565b6080810151600111801590613ab2575060a0810151600111155b613b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610c7b565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff1615613bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b613bc560006137ba565b613bcd61184e565b6003556004544210613be357613be1614c9c565b565b613be1614fb1565b602254600090640100000000900460ff16613c0e57613c0c85856001614199565b505b600080613c1b8786614642565b91509150816060015142101580613c39575060225460ff1615156001145b613c9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610c7b565b60408201518015613d9f57602454613cd390610100900473ffffffffffffffffffffffffffffffffffffffff1688836144d2565b73ffffffffffffffffffffffffffffffffffffffff88166000908152602760205260409020805483908110613d0a57613d0a615571565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613d4490899083906149ae565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b6000818310613db95781613dbb565b825b9392505050565b6000856001613dd382826000614b1d565b602254640100000000900460ff1615613e48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b6022546301000000900460ff1615613ebc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610c7b565b600854851015613f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610c7b565b600754851115613f94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610c7b565b602454613fbe90610100900473ffffffffffffffffffffffffffffffffffffffff16883089614810565b6000613fc986610d13565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b905290925090606081016140bc8a8a615634565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155614118908b908a906149ae565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b600061419442600454613daa565b905090565b60608360016141aa82826000614b1d565b602254640100000000900460ff161561421f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610c7b565b60225462010000900460ff1615614292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610c7b565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff8111156142d5576142d561549d565b6040519080825280602002602001820160405280156142fe578160200160208202803683370190505b50925060005b6010548110156144c85773ffffffffffffffffffffffffffffffffffffffff87166000908152601860209081526040808320848452909152902054845185908390811061435357614353615571565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8816600090815260188252604080822084835290925290812081905584518590839081106143a7576143a7615571565b602002602001015111156144c057614416601082815481106143cb576143cb615571565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061440957614409615571565b60200260200101516144d2565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061446057614460615571565b60200260200101516010848154811061447b5761447b615571565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101614304565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916145699190615717565b6000604051808303816000865af19150503d80600081146145a6576040519150601f19603f3d011682016040523d82523d6000602084013e6145ab565b606091505b50915091508180156145d55750805115806145d55750808060200190518101906145d59190615733565b61463b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610c7b565b5050505050565b6146776040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156147945760005b73ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020548110156147925773ffffffffffffffffffffffffffffffffffffffff851660009081526027602052604090208054829081106146e6576146e6615571565b906000526020600020906005020160000154840361478a5773ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902080548290811061473557614735615571565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614792565b600101614682565b505b82158015906147a35750815183145b614809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610c7b565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916148af9190615717565b6000604051808303816000865af19150503d80600081146148ec576040519150601f19603f3d011682016040523d82523d6000602084013e6148f1565b606091505b509150915081801561491b57508051158061491b57508080602001905181019061491b9190615733565b6149a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610c7b565b505050505050565b60006149b984612a96565b90508115614a6d5782601c60008282546149d39190615634565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604081208054859290614a0d908490615634565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614a685773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614a62908490615634565b90915550505b614b14565b82601c6000828254614a7f91906155cf565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604081208054859290614ab99084906155cf565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614b145773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054859290614b0e9084906155cf565b90915550505b61162d84600060015b602254640100000000900460ff16614b3d578115614b3d57614b3d613b46565b8015614b7357614b4c836111ce565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff83161561223e576000806000614b9d86612243565b6022549295509093509150640100000000900460ff16614bc057614bc08661501a565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c60205260409020829055828110614c44576000614bfb84836155cf565b905080601d54614c0b9190615634565b601d55614c188185615634565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f6020526040902055506149a6565b6000614c5082856155cf565b905080601d54614c6091906155cf565b601d55614c6d81856155cf565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614ca4614fb1565b60005b601254811015614d8b57600060128281548110614cc657614cc6615571565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614d82576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614d5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d7f9190615750565b50505b50600101614ca7565b50600062093a8060045442614da091906155cf565b614daa91906155f9565b905060005b601054811015614f835760108181548110614dcc57614dcc615571565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e679190615647565b614e72836001615634565b62093a80614e7f846136a3565b614e8991906155e2565b614e9391906155e2565b111560108281548110614ea857614ea8615571565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614f7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7b9190615381565b50600101614daf565b5062093a80614f93826001615634565b614f9d91906155e2565b600454614faa9190615634565b6004556136a05b6000614fbb6119c2565b905060005b60165481101561500b57818181518110614fdc57614fdc615571565b602002602001015160168281548110614ff757614ff7615571565b600091825260209091200155600101614fc0565b50615014614186565b60055550565b73ffffffffffffffffffffffffffffffffffffffff8116156136a057600061504182610a9d565b905060005b81518110156150a55781818151811061506157615061615571565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101615046565b5060005b815181101561223e57601681815481106150c5576150c5615571565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff861683526017825260408084208585529092529120556001016150a9565b803573ffffffffffffffffffffffffffffffffffffffff81168114612af457600080fd5b60006020828403121561513c57600080fd5b613dbb82615106565b6020808252825182820181905260009190848201906040850190845b8181101561517d57835183529284019291840191600101615161565b50909695505050505050565b80151581146136a057600080fd5b6000806000606084860312156151ac57600080fd5b833592506151bc60208501615106565b915060408401356151cc81615189565b809150509250925092565b6000602082840312156151e957600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561517d57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161520c565b6000806040838503121561525157600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b828110156152c15781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a0909301929085019060010161527d565b5091979650505050505050565b600080604083850312156152e157600080fd5b6152ea83615106565b91506152f860208401615106565b90509250929050565b6000806000806080858703121561531757600080fd5b843561532281615189565b9350602085013561533281615189565b9250604085013561534281615189565b9150606085013561535281615189565b939692955090935050565b60005b83811015615378578181015183820152602001615360565b50506000910152565b60208152600082518060208401526153a081604085016020870161535d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156153e557600080fd5b6153ee83615106565b946020939093013593505050565b6000806040838503121561540f57600080fd5b61541883615106565b9150602083013561542881615189565b809150509250929050565b6000806000806080858703121561544957600080fd5b61545285615106565b93506020850135925061546760408601615106565b915061547560608601615106565b905092959194509250565b60006020828403121561549257600080fd5b8135613dbb81615189565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c082840312156154de57600080fd5b82601f8301126154ed57600080fd5b60405160c0810181811067ffffffffffffffff82111715615537577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561554c57600080fd5b845b8181101561556657803583526020928301920161554e565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610d3957610d396155a0565b8082028115828204841417610d3957610d396155a0565b60008261562f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610d3957610d396155a0565b60006020828403121561565957600080fd5b5051919050565b600181811c9082168061567457607f821691505b602082108103610c0c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b805169ffffffffffffffffffff81168114612af457600080fd5b600080600080600060a086880312156156df57600080fd5b6156e8866156ad565b945060208601519350604086015192506060860151915061570b608087016156ad565b90509295509295909350565b6000825161572981846020870161535d565b9190910192915050565b60006020828403121561574557600080fd5b8151613dbb81615189565b6000806040838503121561576357600080fd5b50508051602090910151909290915056fea26469706673582212201094739c3c5858a4971e25d652206dbcc4add942108dc3182acb57123271e4cc64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000d893522d2ccd40ea6c1414815e3ead1b58a83d5100000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----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): 0xD893522D2CCd40eA6C1414815e3eAD1B58a83D51
-----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] : 000000000000000000000000d893522d2ccd40ea6c1414815e3ead1b58a83d51
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
120046:2941:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47822:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100497:316;;;;;;:::i;:::-;;:::i;:::-;;;1700:25:1;;;1688:2;1673:18;100497:316:0;1554:177:1;50720:222:0;;;;;;:::i;:::-;;:::i;45824:109::-;;;:::i;:::-;;;;;;;:::i;30705:141::-;;;;;;:::i;:::-;;:::i;:::-;;98061:190;;;;;;:::i;:::-;;:::i;48530:339::-;;;:::i;91828:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;51552:179::-;;;;;;:::i;:::-;;:::i;80688:35::-;;;;;;;;;;;;4261:42:1;4249:55;;;4231:74;;4219:2;4204:18;80688:35:0;4058:253:1;45236:459:0;;;;;;:::i;:::-;;:::i;:::-;;;4746:14:1;;4739:22;4721:41;;4709:2;4694:18;45236:459:0;4581:187:1;41682:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;54079:1752;;;;;;:::i;:::-;;:::i;71087:572::-;;;;;;:::i;:::-;;:::i;49931:127::-;;;;;;:::i;:::-;50024:26;;49997:7;50024:26;;;:17;:26;;;;;;;49931:127;40518:48;;40560:6;40518:48;;60740:309;;;;;;:::i;:::-;;:::i;40107:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;120248:47;;;:::i;:::-;;;;;;;:::i;80460:36::-;;;;;;;;;52714:181;;;;;;:::i;:::-;;:::i;30473:29::-;;;;;;;;;42515:31;;;:::i;122239:745::-;;;:::i;49539:111::-;49620:22;;49539:111;;40428:55;;;;;;:::i;:::-;;;;;;;;;;;;;;40910:54;;;;;;:::i;:::-;;;;;;;;;;;;;;39310:32;;;;;;46829:681;;;:::i;80170:45::-;;;;;;;;;;;;121986:245;;;;;;:::i;:::-;;:::i;87019:2692::-;;;;;;:::i;:::-;;:::i;61997:206::-;;;;;;:::i;:::-;;:::i;81531:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;7473:25:1;;;7529:2;7514:18;;7507:34;;;;7557:18;;;7550:34;;;;7615:2;7600:18;;7593:34;7658:3;7643:19;;7636:35;7460:3;7445:19;81531:53:0;7214:463:1;30854:271:0;;;:::i;41477:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;53091:199;;;;;;:::i;:::-;;:::i;72455:1099::-;;;;;;:::i;:::-;;:::i;42455:34::-;;;;;;;;;;;;89772:1961;;;;;;:::i;:::-;;:::i;:::-;;;;7884:25:1;;;7940:2;7925:18;;7918:34;;;;7968:18;;;7961:34;7872:2;7857:18;89772:1961:0;7682:319:1;30446:20:0;;;;;;;;;72059:161;;;;;;:::i;:::-;;:::i;41804:26::-;;;;;;;;;52008:224;;;;;;:::i;:::-;;:::i;39431:55::-;;;;;;94669:1555;;;;;;:::i;:::-;;:::i;39155:62::-;;;;;;121631:347;;;:::i;61535:172::-;;;;;;:::i;:::-;;:::i;53443:444::-;;;;;;:::i;:::-;;:::i;39001:29::-;;;;;;92037:133;;;;;;:::i;:::-;92134:21;;92107:7;92134:21;;;:12;:21;;;;;:28;;92037:133;39081:50;;;;;;38674:30;;;;;;96278:1648;;;;;;:::i;:::-;;:::i;51177:166::-;;;;;;:::i;:::-;;:::i;75529:483::-;;;;;;:::i;:::-;;:::i;56851:800::-;;;;;;:::i;:::-;;:::i;49297:128::-;;;;;;:::i;:::-;49391:26;;49364:7;49391:26;;;:17;:26;;;;;;;49297:128;76332:207;;;;;;:::i;:::-;;:::i;49032:113::-;49114:23;;49032:113;;71823:97;;;:::i;56085:610::-;;;;;;:::i;:::-;;:::i;38894:27::-;;;;;;39569:51;;;;;;39645:59;;;;;;46307:452;;;;;;:::i;:::-;;:::i;69148:761::-;;;;;;:::i;:::-;;:::i;74017:958::-;;;;;;:::i;:::-;;:::i;70008:482::-;;;:::i;47822:529::-;47876:27;47916;47946:17;:15;:17::i;:::-;48001:12;:19;47916:47;;-1:-1:-1;47987:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47987:34:0;-1:-1:-1;48038:26:0;;;48067:1;48038:26;;;:17;:26;;;;;;47974:47;;-1:-1:-1;48038:30:0;48034:310;;48089:9;48084:249;48108:12;:19;48104:23;;48084:249;;;48298:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;48217:32;;;:23;:32;;;;;:35;;;;;;;;;48201:13;;48257:4;;48217:35;48201:10;;48315:1;;48201:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;48171:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;48170:91;;;;:::i;:::-;48169:148;;;;:::i;:::-;48153:10;48164:1;48153:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;48129:3;;48084:249;;;;48034:310;47905:446;47822:529;;;:::o;100497:316::-;100628:7;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;;;;;;;;;34722:1;35461:18;;100656:17:::1;::::0;::::1;::::0;::::1;;;:26;100648:57;;;::::0;::::1;::::0;;11857:2:1;100648:57:0::1;::::0;::::1;11839:21:1::0;11896:2;11876:18;;;11869:30;11935:20;11915:18;;;11908:48;11973:18;;100648:57:0::1;11655:342:1::0;100648:57:0::1;100723:82;100739:10;100751:19;100772:6;100780:24;100723:15;:82::i;:::-;34678:1:::0;35640:7;:22;100716:89;100497:316;-1:-1:-1;;;;100497:316:0:o;50720:222::-;50829:19;;50894:28;;50779:7;;50806:127;;50864:26;50829:19;50864:4;:26;:::i;:::-;50863:59;;;;:::i;:::-;50806:8;:127::i;:::-;50799:134;50720:222;-1:-1:-1;;50720:222:0:o;45824:109::-;45877:16;45913:12;45906:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45824:109;:::o;30705:141::-;31185:5;;;;31171:10;:19;31163:79;;;;;;;12204:2:1;31163:79:0;;;12186:21:1;12243:2;12223:18;;;12216:30;12282:34;12262:18;;;12255:62;12353:17;12333:18;;;12326:45;12388:19;;31163:79:0;12002:411:1;31163:79:0;30777:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;30816:22:::1;::::0;4231:74:1;;;30816:22:0::1;::::0;4219:2:1;4204:18;30816:22:0::1;;;;;;;30705:141:::0;:::o;98061:190::-;98146:7;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;98173:70:::1;98186:10;::::0;98210:9;98221:4;98227:15:::1;98173:12;:70::i;:::-;34678:1:::0;35640:7;:22;98166:77;98061:190;-1:-1:-1;;;98061:190:0:o;48530:339::-;48680:17;:24;48585:41;;48666:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48666:39:0;;48639:66;;48723:9;48718:144;48742:17;:24;48738:28;;48718:144;;;40560:6;48818:14;48830:1;48818:11;:14::i;:::-;:32;;;;:::i;:::-;48788:24;48813:1;48788:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;48768:3;;48718:144;;;;48530:339;:::o;91828:133::-;91932:21;;;;;;;:12;:21;;;;;;;;91925:28;;;;;;;;;;;;;;;;;91892:20;;91925:28;;91932:21;;91925:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91828:133;;;:::o;51552:179::-;51667:32;;;51621:7;51667:32;;;:17;:32;;;;;;51649:15;;38802:4;;51649:50;;;:::i;:::-;51648:75;;;;:::i;45236:459::-;45353:32;;;45332:4;45353:32;;;:13;:32;;;;;;;;45348:297;;-1:-1:-1;45394:5:0;45387:12;;45348:297;45419:25;;;;;:60;;-1:-1:-1;45448:31:0;;;;45419:60;45415:230;;;-1:-1:-1;45488:5:0;45481:12;;45415:230;45528:5;;;;;;45513:20;;;;45509:136;;-1:-1:-1;45542:4:0;45535:11;;45509:136;45584:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;45580:65;;-1:-1:-1;45641:4:0;45634:11;;45580:65;-1:-1:-1;45681:5:0;45236:459;;;;:::o;54079:1752::-;54142:24;;;54303:20;54315:7;54303:11;:20::i;:::-;54283:40;-1:-1:-1;54354:23:0;;;;54353:81;;54408:26;;;;;4261:42:1;4249:55;;54408:26:0;;;4231:74:1;38409:42:0;;54408:15;;4204:18:1;;54408:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54353:81;;;54381:24;;;;;4261:42:1;4249:55;;54381:24:0;;;4231:74:1;38409:42:0;;54381:15;;4204:18:1;;54381:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54334:100;;54540:19;38802:4;38409:42;54664:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;54605:24;;54582:20;;54563:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;54562:145;;;;:::i;:::-;54540:167;-1:-1:-1;54816:19:0;;55031:23;;;;55030:94;;55089:35;55114:9;55089:24;:35::i;:::-;55030:94;;;55058:28;55078:7;55058:19;:28::i;:::-;55001:123;-1:-1:-1;55145:30:0;;55141:323;;55196:27;55270:26;55227:39;38802:4;55227:16;:39;:::i;:::-;55226:70;;;;:::i;:::-;55196:100;;38802:4;55370:20;;55348:19;:42;;;;:::i;:::-;55347:67;;;;:::i;:::-;55333:81;;55176:254;55141:323;;;55463:1;55449:15;;55141:323;54846:699;55632:11;55618;:25;:53;;55660:11;55618:53;;;55646:11;55618:53;55598:74;;55762:20;;55743:16;:39;55739:84;;;55803:20;;55784:39;;55739:84;54168:1663;;;;54079:1752;;;:::o;71087:572::-;42725:5;;;;42711:10;:19;;:79;;-1:-1:-1;42748:42:0;42734:10;:56;42711:79;42703:113;;;;;;;12809:2:1;42703:113:0;;;12791:21:1;12848:2;12828:18;;;12821:30;12887:23;12867:18;;;12860:51;12928:18;;42703:113:0;12607:345:1;42703:113:0;71289:13:::1;:30:::0;;71330:38;;71289:30;;::::1;;;71330:38:::0;;;71289:30:::1;71330:38:::0;::::1;;;;71379:50:::0;::::1;::::0;;::::1;;;;::::0;;71570:23;:50;::::1;;;-1:-1:-1::0;71598:22:0::1;::::0;;;::::1;;;71597:23;71570:50;71567:84;;;71622:22;:29:::0;;;::::1;::::0;::::1;::::0;;71567:84:::1;71087:572:::0;;;;:::o;60740:309::-;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;60838:22:::1;::::0;;;::::1;;;60837:23;60829:60;;;::::0;::::1;::::0;;13159:2:1;60829:60:0::1;::::0;::::1;13141:21:1::0;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;60829:60:0::1;12957:348:1::0;60829:60:0::1;60908:23;::::0;;;::::1;;;:32;60900:70;;;::::0;::::1;::::0;;13512:2:1;60900:70:0::1;::::0;::::1;13494:21:1::0;13551:2;13531:18;;;13524:30;13590:27;13570:18;;;13563:55;13635:18;;60900:70:0::1;13310:349:1::0;60900:70:0::1;-1:-1:-1::0;34678:1:0;35640:7;:22;60740:309::o;120248:47::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;52714:181::-;52781:7;38802:4;52835:28;;52809:23;52824:7;52809:14;:23::i;:::-;:54;;;;:::i;42515:31::-;;;;;;;:::i;122239:745::-;122729:9;;122660:80;;;;;:60;122729:9;;;122660:80;;;4231:74:1;122295:25:0;;;;122667:42;;122660:60;;4204:18:1;;122660:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122635:105;;122755:32;122842:10;;;;;;;;;;;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122816:21;:19;:21::i;:::-;122791:47;;:14;:47;:::i;:::-;122790:76;;;;:::i;:::-;122755:111;-1:-1:-1;122901:33:0;122755:111;122929:4;122901:33;:::i;:::-;122881:53;;122502:473;;122239:745;:::o;46829:681::-;46877:41;46935:23;;46962:1;46935:28;:59;;;-1:-1:-1;46967:22:0;;:27;46935:59;46931:572;;;47018:21;47011:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46829:681;:::o;46931:572::-;47122:12;:19;47108:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47108:34:0;;47081:61;;47162:9;47157:289;47181:21;:28;47177:32;;47157:289;;;47389:22;;47364:14;47376:1;47364:11;:14::i;:::-;47346;;47317:26;:24;:26::i;:::-;:43;;;;:::i;:::-;47316:62;;;;:::i;:::-;:69;;47381:4;47316:69;:::i;:::-;47315:96;;;;:::i;:::-;47265:21;47287:1;47265:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;47235:24;47260:1;47235:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;47211:3;;47157:289;;121986:245;42725:5;;;;42711:10;:19;;:79;;-1:-1:-1;42748:42:0;42734:10;:56;42711:79;42703:113;;;;;;;12809:2:1;42703:113:0;;;12791:21:1;12848:2;12828:18;;;12821:30;12887:23;12867:18;;;12860:51;12928:18;;42703:113:0;12607:345:1;42703:113:0;122083:37:::1;::::0;::::1;122075:71;;;::::0;::::1;::::0;;14308:2:1;122075:71:0::1;::::0;::::1;14290:21:1::0;14347:2;14327:18;;;14320:30;14386:23;14366:18;;;14359:51;14427:18;;122075:71:0::1;14106:345:1::0;122075:71:0::1;122159:15;:64:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;121986:245::o;87019:2692::-;87210:21;;;87108:32;87210:21;;;:12;:21;;;;;:32;;87108;;87210:21;87232:9;;87210:32;;;;;;:::i;:::-;;;;;;;;;87179:63;;;;;;;;87210:32;;;;;;;87179:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87425:28;;;;;:19;:28;;;;;;87179:63;;-1:-1:-1;;87421:224:0;;;-1:-1:-1;87518:25:0;;;;87421:224;;;-1:-1:-1;87605:28:0;;;;;;;:19;:28;;;;;;87421:224;87734:15;87704:9;:26;;;:45;87700:1802;;87929:26;;;;87898:28;;;;;;;:19;:28;;;;;;:57;87894:1087;;;87975:26;88033:17;88004:9;:26;;;:46;;;;:::i;:::-;87975:75;;88069:25;88115:9;:26;;;88097:15;:44;;;;:::i;:::-;88069:72;-1:-1:-1;88221:33:0;88257:38;88272:22;88293:1;88272:18;:22;:::i;88257:38::-;88221:74;-1:-1:-1;88512:17:0;88584:21;88588:17;88512;88584:21;:::i;:::-;88533:46;88561:18;88533:25;:46;:::i;:::-;88532:74;;;;:::i;:::-;88512:94;-1:-1:-1;88665:38:0;88686:17;88665:18;:38;:::i;:::-;88652:52;;:9;:52;:::i;:::-;88625:79;;87956:764;;;;87700:1802;;87894:1087;88964:1;88937:28;;87700:1802;;;89126:21;89181:20;89233:17;89204:9;:26;;;:46;;;;:::i;:::-;89181:69;;89269:20;89321:15;89292:9;:26;;;:44;;;;:::i;:::-;89269:67;-1:-1:-1;89403:1:0;89372:27;89269:67;89372:12;:27;:::i;:::-;89371:33;;;;:::i;:::-;89355:49;;89162:258;;89461:29;89476:13;89461:14;:29::i;:::-;89434:56;;89046:456;87700:1802;89624:9;:25;;;89597:24;:52;89593:110;;;89678:9;:25;;;89651:52;;89593:110;87142:2569;;87019:2692;;;;:::o;61997:206::-;62099:16;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;62135:60:::1;62146:10;62158:19:::0;62179:15;62135:10:::1;:60::i;81531:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81531:53:0;;-1:-1:-1;81531:53:0;;;:::o;30854:271::-;30923:14;;;;30909:10;:28;30901:94;;;;;;;14658:2:1;30901:94:0;;;14640:21:1;14697:2;14677:18;;;14670:30;14736:34;14716:18;;;14709:62;14807:23;14787:18;;;14780:51;14848:19;;30901:94:0;14456:417:1;30901:94:0;31024:5;;;31031:14;31011:35;;;31024:5;;;;15113:34:1;;31031:14:0;;;;15178:2:1;15163:18;;15156:43;31011:35:0;;15025:18:1;31011:35:0;;;;;;;31065:14;;;;31057:22;;;;;;31065:14;;;31057:22;;;;31090:27;;;30854:271::o;53091:199::-;53169:7;38802:4;53230:28;;53197:30;53213:13;53197:15;:30::i;72455:1099::-;42928:5;;72541:12;;42928:5;;42914:10;:19;;:74;;;42937:51;42955:10;42967:20;42937:17;:51::i;:::-;42906:107;;;;;;;15412:2:1;42906:107:0;;;15394:21:1;15451:2;15431:18;;;15424:30;15490:22;15470:18;;;15463:50;15530:18;;42906:107:0;15210:344:1;42906:107:0;72639:27:::1;::::0;::::1;72623:13;72639:27:::0;;;:13:::1;:27;::::0;;;;;::::1;;::::0;72893:54;::::1;;;-1:-1:-1::0;72905:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;72937:10;72905:42;72893:54;72892:113;;;;72971:8;72970:9;:34;;;;-1:-1:-1::0;72998:5:0::1;::::0;::::1;;72984:10;:19;72970:34;72870:677;;;73317:66;73345:12;73359:10;73371:11;73317:27;:66::i;72870:677::-;73499:36;::::0;::::1;::::0;;15761:2:1;73499:36:0::1;::::0;::::1;15743:21:1::0;15800:2;15780:18;;;15773:30;15839:28;15819:18;;;15812:56;15885:18;;73499:36:0::1;15559:350:1::0;43024:1:0::1;72455:1099:::0;;;:::o;89772:1961::-;90075:26;;;89873:27;90075:26;;;:17;:26;;;;;;;89873:27;90262:24;90093:7;90262:15;:24::i;:::-;90362:26;;;90299:33;90362:26;;;:17;:26;;;;;;90239:47;;-1:-1:-1;90299:33:0;90362:31;:66;;;;-1:-1:-1;90397:26:0;;;;;;;:17;:26;;;;;;:31;90362:66;90361:143;;;-1:-1:-1;90472:31:0;;;;;;;:22;:31;;;;;;90448:55;;;90361:143;90343:638;;;-1:-1:-1;90745:20:0;90343:638;;;90933:31;;;;;;;:22;:31;;;;;;90968:1;;90910:54;;:20;:54;:::i;:::-;90909:60;;;;:::i;:::-;90881:88;;90343:638;91116:1;91094:23;;91133:9;91128:598;91152:21;;;;;;;:12;:21;;;;;:28;91148:32;;91128:598;;;91233:21;;;91202:28;91233:21;;;:12;:21;;;;;:24;;91255:1;;91233:24;;;;;;:::i;:::-;;;;;;;;;;;91202:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91329:32;91364:34;91387:7;91396:1;91364:22;:34::i;:::-;91480:19;;;;91329:69;;-1:-1:-1;91460:17:0;38802:4;91575:52;91602:25;91329:69;91575:52;:::i;:::-;91562:66;;:9;:66;:::i;:::-;91561:91;;;;:::i;:::-;91548:105;;:9;:105;:::i;:::-;91514:139;-1:-1:-1;91668:46:0;91514:139;91668:46;;:::i;:::-;;-1:-1:-1;;91182:3:0;;;;;-1:-1:-1;91128:598:0;;-1:-1:-1;;91128:598:0;;;90002:1731;89772:1961;;;;;:::o;72059:161::-;42725:5;;;;42711:10;:19;;:79;;-1:-1:-1;42748:42:0;42734:10;:56;42711:79;42703:113;;;;;;;12809:2:1;42703:113:0;;;12791:21:1;12848:2;12828:18;;;12821:30;12887:23;12867:18;;;12860:51;12928:18;;42703:113:0;12607:345:1;42703:113:0;72180:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;72144:68;;::::1;72180:32;::::0;;::::1;72179:33;72144:68;::::0;;72059:161::o;52008:224::-;52074:7;52208:15;;52177:28;;:46;;;;:::i;:::-;52102:24;;;;;4261:42:1;4249:55;;52102:24:0;;;4231:74:1;38802:4:0;;;;38409:42;;52102:15;;4204:18:1;;52102:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;94669:1555::-;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;94810:13:::1;::::0;;;::::1;;;94809:14;94801:41;;;::::0;::::1;::::0;;16116:2:1;94801:41:0::1;::::0;::::1;16098:21:1::0;16155:2;16135:18;;;16128:30;16194:16;16174:18;;;16167:44;16228:18;;94801:41:0::1;15914:338:1::0;94801:41:0::1;94910:22;::::0;;;::::1;;;94909:23;94901:60;;;::::0;::::1;::::0;;13159:2:1;94901:60:0::1;::::0;::::1;13141:21:1::0;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;94901:60:0::1;12957:348:1::0;94901:60:0::1;95025:40;95036:10;95048;95060:4;95025:10;:40::i;:::-;;95127:28;95157:21:::0;95182:29:::1;95192:10;95204:6;95182:9;:29::i;:::-;95126:85;;;;95261:15;95301:8;95279:9;:19;;;:30;;;;:::i;:::-;95261:48:::0;-1:-1:-1;95480:12:0::1;::::0;95440:91:::1;::::0;95480:12:::1;::::0;::::1;;;95495:10;95515:4;95522:8:::0;95440:31:::1;:91::i;:::-;95880:186;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;95927:25:::0;;::::1;::::0;95880:186;;::::1;::::0;;;;;;;;95989:26;;::::1;::::0;95880:186;;;;;96030:25;;::::1;::::0;95880:186;;;;95851:10:::1;-1:-1:-1::0;95838:24:0;;;:12:::1;:24:::0;;;;;;;:39;;95863:13;;95838:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96110:42;96125:10;96137:8;96147:4;96110:14;:42::i;:::-;96170:46;::::0;;16776:25:1;;;16832:2;16817:18;;16810:34;;;96187:10:0::1;::::0;96170:46:::1;::::0;16749:18:1;96170:46:0::1;;;;;;;-1:-1:-1::0;;34678:1:0;35640:7;:22;-1:-1:-1;;;94669:1555:0:o;121631:347::-;121683:3;121726:14;121742:9;121755:17;121774:22;121800:15;;;;;;;;;;;:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;121725:108;;;;;;;;;121861:1;121852:5;:10;;:27;;;;-1:-1:-1;121866:13:0;;;121852:27;:57;;;;;121902:7;121883:26;;:15;:26;;;;121852:57;121844:93;;;;;;;17719:2:1;121844:93:0;;;17701:21:1;17758:2;17738:18;;;17731:30;17797:25;17777:18;;;17770:53;17840:18;;121844:93:0;17517:347:1;121844:93:0;-1:-1:-1;121965:5:0;;121631:347;-1:-1:-1;;;121631:347:0:o;61535:172::-;61614:16;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;61650:49:::1;61661:10;61673:19:::0;61694:4:::1;61650:10;:49::i;:::-;34678:1:::0;35640:7;:22;61643:56;61535:172;-1:-1:-1;;61535:172:0:o;53443:444::-;53522:25;;;53499:7;53522:25;;;:19;:25;;;;;;;;53518:362;;;-1:-1:-1;53725:4:0;53443:444::o;53518:362::-;-1:-1:-1;53837:31:0;;;;;;;;:25;:31;;;;;;;;53443:444::o;53518:362::-;53443:444;;;:::o;96278:1648::-;34722:1;35328:7;;:19;35320:63;;;;;;;11497:2:1;35320:63:0;;;11479:21:1;11536:2;11516:18;;;11509:30;11575:33;11555:18;;;11548:61;11626:18;;35320:63:0;11295:355:1;35320:63:0;34722:1;35461:18;;96420:13:::1;::::0;;;::::1;;;96419:14;96411:41;;;::::0;::::1;::::0;;16116:2:1;96411:41:0::1;::::0;::::1;16098:21:1::0;16155:2;16135:18;;;16128:30;16194:16;16174:18;;;16167:44;16228:18;;96411:41:0::1;15914:338:1::0;96411:41:0::1;96520:22;::::0;;;::::1;;;96519:23;96511:60;;;::::0;::::1;::::0;;13159:2:1;96511:60:0::1;::::0;::::1;13141:21:1::0;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;96511:60:0::1;12957:348:1::0;96511:60:0::1;96635:40;96646:10;96658;96670:4;96635:10;:40::i;:::-;;96737:28;96767:21:::0;96792:29:::1;96802:10;96814:6;96792:9;:29::i;:::-;96736:85;;;;96876:15;96860:13;:31;96852:65;;;::::0;::::1;::::0;;18071:2:1;96852:65:0::1;::::0;::::1;18053:21:1::0;18110:2;18090:18;;;18083:30;18149:23;18129:18;;;18122:51;18190:18;;96852:65:0::1;17869:345:1::0;96852:65:0::1;96963:17;97013:15;96984:9;:26;;;:44;96983:97;;97079:1;96983:97;;;97061:15;97032:9;:26;;;:44;;;;:::i;:::-;96963:117:::0;-1:-1:-1;97091:16:0::1;97110:31;97126:15;97110:13:::0;:31:::1;:::i;:::-;97091:50;;97247:9;97236:8;:20;97228:57;;;::::0;::::1;::::0;;18421:2:1;97228:57:0::1;::::0;::::1;18403:21:1::0;18460:2;18440:18;;;18433:30;18499:26;18479:18;;;18472:54;18543:18;;97228:57:0::1;18219:348:1::0;97228:57:0::1;97316:13;;97304:8;:25;;97296:64;;;::::0;::::1;::::0;;18774:2:1;97296:64:0::1;::::0;::::1;18756:21:1::0;18813:2;18793:18;;;18786:30;18852:28;18832:18;;;18825:56;18898:18;;97296:64:0::1;18572:350:1::0;97296:64:0::1;97391:28;;97379:8;:40;;97371:80;;;::::0;::::1;::::0;;19129:2:1;97371:80:0::1;::::0;::::1;19111:21:1::0;19168:2;19148:18;;;19141:30;19207:29;19187:18;;;19180:57;19254:18;;97371:80:0::1;18927:351:1::0;97371:80:0::1;97535:174;;;;;;;;97561:6;97535:174;;;;97582:15;97535:174;;;;97612:9;:19;;;97535:174;;;;97646:13;97535:174;;;;97674:24;97689:8;97674:14;:24::i;:::-;97535:174:::0;;97506:10:::1;97493:24;::::0;;;:12:::1;:24;::::0;;;;:39;;97518:13;;97493:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97778:48;97802:10;97814:5;97821:4;97778:23;:48::i;:::-;97844:74;::::0;;19514:25:1;;;19570:2;19555:18;;19548:34;;;97887:15:0::1;19598:18:1::0;;;19591:34;19656:2;19641:18;;19634:34;;;97844:74:0;;97857:10:::1;::::0;97844:74:::1;::::0;;;;;19501:3:1;97844:74:0;;::::1;-1:-1:-1::0;;34678:1:0;35640:7;:22;-1:-1:-1;;;;96278:1648:0:o;51177:166::-;51285:26;;;51239:7;51285:26;;;:17;:26;;;;;;51267:15;;38802:4;;51267:44;;;:::i;75529:483::-;42928:5;;75695:20;;42928:5;;42914:10;:19;;:74;;;42937:51;42955:10;42967:20;42937:17;:51::i;:::-;42906:107;;;;;;;15412:2:1;42906:107:0;;;15394:21:1;15451:2;15431:18;;;15424:30;15490:22;15470:18;;;15463:50;15530:18;;42906:107:0;15210:344:1;42906:107:0;75746:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;75728:17:::1;:61:::0;;75792:9;;75746:42;75728:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;75875:25;75812:16;75829:20;:42;75850:20;75829:42;;;;;;;;;;;;;;;;75812:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;75930:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;75911:18:::1;:62:::0;;75976:28;;75930:42;75911:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;75529:483:::0;;;;;:::o;56851:800::-;56931:34;;;;;;;:19;:34;;;;;;;;56923:60;;;;;;;19881:2:1;56923:60:0;;;19863:21:1;19920:2;19900:18;;;19893:30;19959:15;19939:18;;;19932:43;19992:18;;56923:60:0;19679:337:1;56923:60:0;57002:36;;;;;;;:21;:36;;;;;;;;57039:10;57002:48;;;;;;;;;;56994:90;;;;;;;20223:2:1;56994:90:0;;;20205:21:1;20262:2;20242:18;;;20235:30;20301:31;20281:18;;;20274:59;20350:18;;56994:90:0;20021:353:1;56994:90:0;57230:10;57179:22;57204:37;;;:25;:37;;;;;;;;57256:28;;57252:182;;57411:10;57393:29;;;;:17;:29;;;;;;;;;;57356:33;;;;;;;;;:66;;57393:29;;57356:33;;:66;;57393:29;;57356:66;:::i;:::-;;;;-1:-1:-1;;57252:182:0;57502:10;57476:37;;;;:25;:37;;;;;;;;:53;;;;:37;:53;;;;;;;;57614:17;:29;;;;;;57578:32;;;;;;;;:65;;57614:29;;57578:32;;:65;;57614:29;;57578:65;:::i;:::-;;;;-1:-1:-1;;;;56851:800:0:o;76332:207::-;42928:5;;76440:20;;42928:5;;42914:10;:19;;:74;;;42937:51;42955:10;42967:20;42937:17;:51::i;:::-;42906:107;;;;;;;15412:2:1;42906:107:0;;;15394:21:1;15451:2;15431:18;;;15424:30;15490:22;15470:18;;;15463:50;15530:18;;42906:107:0;15210:344:1;42906:107:0;-1:-1:-1;76473:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;76332:207::o;71823:97::-;42725:5;;;;42711:10;:19;;:79;;-1:-1:-1;42748:42:0;42734:10;:56;42711:79;42703:113;;;;;;;12809:2:1;42703:113:0;;;12791:21:1;12848:2;12828:18;;;12821:30;12887:23;12867:18;;;12860:51;12928:18;;42703:113:0;12607:345:1;42703:113:0;71898:14:::1;::::0;;71880:32;;::::1;71898:14;::::0;;::::1;71897:15;71880:32;::::0;;71823:97::o;56085:610::-;56184:10;56164:31;;;;:19;:31;;;;;;;;56156:57;;;;;;;19881:2:1;56156:57:0;;;19863:21:1;19920:2;19900:18;;;19893:30;19959:15;19939:18;;;19932:43;19992:18;;56156:57:0;19679:337:1;56156:57:0;56299:10;56277:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;56276:50;56224:102;;;;;;;56429:25;:41;;;;;;;;:55;56425:263;;56500:41;;;56552:1;56500:41;;;:25;:41;;;;;;;;:54;;;;;;56643:17;:33;;;;;;56628:10;56610:29;;;;;;;:66;;56643:33;;56610:29;;:66;;56643:33;;56610:66;:::i;:::-;;;;-1:-1:-1;;56425:263:0;56085:610;:::o;46307:452::-;46368:16;46397:32;46432:16;46449:9;46432:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;46474:38:0;;46470:282;;46655:4;46613:27;46641:9;46613:38;;;;;;;;:::i;:::-;;;;;;;;;46562:24;46541:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;46540:119;;;;:::i;:::-;46529:130;;46470:282;;;46712:17;46730:9;46712:28;;;;;;;;:::i;:::-;;;;;;;;;46701:39;;46386:373;46307:452;;;:::o;69148:761::-;69265:9;69260:642;69284:16;:23;69280:27;;69260:642;;;69329:32;69364:16;69381:1;69364:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;69402:38:0;;69398:493;;69465:12;:61;;;;69500:22;69523:1;69500:25;;;;;;;;:::i;:::-;;;;;;;;;69482:15;:43;69465:61;69461:415;;;69640:106;;;;;69723:4;69640:106;;;20553:74:1;69730:15:0;20643:18:1;;;20636:34;69640:74:0;;;;;;20526:18:1;;69640:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69607:27;69635:1;69607:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;69818:24;69797:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69769:22;69792:1;69769:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;69461:415;-1:-1:-1;69309:3:0;;69260:642;;;;69148:761;:::o;74017:958::-;42725:5;;;;42711:10;:19;;:79;;-1:-1:-1;42748:42:0;42734:10;:56;42711:79;42703:113;;;;;;;12809:2:1;42703:113:0;;;12791:21:1;12848:2;12828:18;;;12821:30;12887:23;12867:18;;;12860:51;12928:18;;42703:113:0;12607:345:1;42703:113:0;74426:13;;38802:4:::1;-1:-1:-1::0;74426:37:0::1;74418:69;;;::::0;::::1;::::0;;20883:2:1;74418:69:0::1;::::0;::::1;20865:21:1::0;20922:2;20902:18;;;20895:30;20961:21;20941:18;;;20934:49;21000:18;;74418:69:0::1;20681:343:1::0;74418:69:0::1;74611:13:::0;;::::1;::::0;74628:1:::1;-1:-1:-1::0;74611:18:0;::::1;::::0;74610:44:::1;;-1:-1:-1::0;74635:13:0;;::::1;::::0;74652:1:::1;-1:-1:-1::0;74635:18:0::1;74610:44;74602:69;;;::::0;::::1;::::0;;21572:2:1;74602:69:0::1;::::0;::::1;21554:21:1::0;21611:2;21591:18;;;21584:30;21650:14;21630:18;;;21623:42;21682:18;;74602:69:0::1;21370:336:1::0;74602:69:0::1;74706:13:::0;;74684:19:::1;:35:::0;74706:13:::1;74753::::0;::::1;::::0;74730:20:::1;:36:::0;74808:13;;::::1;::::0;74777:28:::1;:44:::0;74859:13;;::::1;::::0;74832:24:::1;:40:::0;74914:13;;::::1;::::0;74883:28:::1;:44:::0;74954:13;::::1;::::0;74938::::1;:29:::0;74017:958::o;70008:482::-;70097:22;;;;;;;70096:23;70088:60;;;;;;;13159:2:1;70088:60:0;;;13141:21:1;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;70088:60:0;12957:348:1;70088:60:0;70210:25;70229:5;70210:18;:25::i;:::-;70305:16;:14;:16::i;:::-;70287:15;:34;70357:12;;70338:15;:31;70334:149;;70386:14;:12;:14::i;:::-;70008:482::o;70334:149::-;70442:29;:27;:29::i;101324:1792::-;101786:22;;101510:7;;101786:22;;;;;101782:194;;101911:53;101922:14;101938:19;101959:4;101911:10;:53::i;:::-;;101782:194;102029:28;102059:21;102084:33;102094:14;102110:6;102084:9;:33::i;:::-;102028:89;;;;102155:9;:26;;;102136:15;:45;;:71;;;-1:-1:-1;102185:14:0;;;;:22;;:14;:22;102136:71;102128:106;;;;;;;21913:2:1;102128:106:0;;;21895:21:1;21952:2;21932:18;;;21925:30;21991:24;21971:18;;;21964:52;22033:18;;102128:106:0;21711:346:1;102128:106:0;102265:19;;;;102301:13;;102297:783;;102715:12;;102679:82;;102715:12;;;;;102730:19;102751:9;102679:27;:82::i;:::-;102833:28;;;;;;;:12;:28;;;;;:43;;102862:13;;102833:43;;;;;;:::i;:::-;;;;;;;;;;;;;102826:50;;;;;;;;;;;;;;;;;;;;;;;;;;102928:48;;102943:14;;102959:9;;102928:14;:48::i;:::-;102998:70;;;22264:25:1;;;22320:2;22305:18;;22298:34;;;102998:70:0;22368:55:1;;;22348:18;;;22341:83;102998:70:0;;;;;;;;;;;22252:2:1;102998:70:0;;;102297:783;103099:9;101324:1792;-1:-1:-1;;;;;;;101324:1792:0:o;26987:106::-;27045:7;27076:1;27072;:5;:13;;27084:1;27072:13;;;27080:1;27072:13;27065:20;26987:106;-1:-1:-1;;;26987:106:0:o;98447:1688::-;98693:7;98662:14;98678:4;43119:49;43143:7;43152:8;43162:5;43119:23;:49::i;:::-;98722:22:::1;::::0;;;::::1;;;98721:23;98713:60;;;::::0;::::1;::::0;;13159:2:1;98713:60:0::1;::::0;::::1;13141:21:1::0;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;98713:60:0::1;12957:348:1::0;98713:60:0::1;98793:13;::::0;;;::::1;;;98792:14;98784:41;;;::::0;::::1;::::0;;16116:2:1;98784:41:0::1;::::0;::::1;16098:21:1::0;16155:2;16135:18;;;16128:30;16194:16;16174:18;;;16167:44;16228:18;;98784:41:0::1;15914:338:1::0;98784:41:0::1;98852:13;;98844:4;:21;;98836:60;;;::::0;::::1;::::0;;18774:2:1;98836:60:0::1;::::0;::::1;18756:21:1::0;18813:2;18793:18;;;18786:30;18852:28;18832:18;;;18825:56;18898:18;;98836:60:0::1;18572:350:1::0;98836:60:0::1;98923:28;;98915:4;:36;;98907:75;;;::::0;::::1;::::0;;19129:2:1;98907:75:0::1;::::0;::::1;19111:21:1::0;19168:2;19148:18;;;19141:30;19207:29;19187:18;;;19180:57;19254:18;;98907:75:0::1;18927:351:1::0;98907:75:0::1;99105:12;::::0;99065:96:::1;::::0;99105:12:::1;::::0;::::1;;;99120:14:::0;99144:4:::1;99151:9:::0;99065:31:::1;:96::i;:::-;99488:23;99514:20;99529:4;99514:14;:20::i;:::-;99633:33;::::0;::::1;99545:14;99633:33:::0;;;:17:::1;:33;::::0;;;;;;;;99572:95;;22681:66:1;22668:2;22664:15;;;22660:88;99572:95:0;;::::1;22648:101:1::0;;;;22765:12;;;22758:28;;;22802:12;;;22795:28;;;22839:12;;;22832:28;99488:46:0;;-1:-1:-1;99545:14:0;22876:13:1;;99572:95:0::1;::::0;;;;;::::1;::::0;;;;;;99562:106;;99572:95:::1;99562:106:::0;;::::1;::::0;99725:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;99759:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;99562:106;;-1:-1:-1;99725:28:0;99759:164;;;99860:22:::1;99878:4:::0;99806:15;99860:22:::1;:::i;:::-;99759:164:::0;;::::1;::::0;;::::1;::::0;;;99725:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;99725: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;99968:47:::1;::::0;99983:14;;99999:9;;99968:14:::1;:47::i;:::-;100033:68;::::0;;23131:25:1;;;23187:2;23172:18;;23165:34;;;23215:18;;;23208:34;;;100033:68:0::1;23278:55:1::0;;;23273:2;23258:18;;23251:83;100033:68:0;::::1;::::0;::::1;::::0;23118:3:1;23103:19;100033:68:0::1;;;;;;;100121:6:::0;98447:1688;-1:-1:-1;;;;;;;;;98447:1688:0:o;45985:133::-;46044:7;46071:39;46080:15;46097:12;;46071:8;:39::i;:::-;46064:46;;45985:133;:::o;62299:1313::-;62447:31;62422:8;62432:4;43119:49;43143:7;43152:8;43162:5;43119:23;:49::i;:::-;62546:22:::1;::::0;;;::::1;;;62545:23;62537:60;;;::::0;::::1;::::0;;13159:2:1;62537:60:0::1;::::0;::::1;13141:21:1::0;13198:2;13178:18;;;13171:30;13237:26;13217:18;;;13210:54;13281:18;;62537:60:0::1;12957:348:1::0;62537:60:0::1;62680:23;::::0;;;::::1;;;:32;62672:70;;;::::0;::::1;::::0;;13512:2:1;62672:70:0::1;::::0;::::1;13494:21:1::0;13551:2;13531:18;;;13524:30;13590:27;13570:18;;;13563:55;13635:18;;62672:70:0::1;13310:349:1::0;62672:70:0::1;62841:29;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;62873:15:::1;62841:47:::0;;63000:12:::1;:19:::0;62986:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;62986:34:0::1;;62969:51;;63038:9;63033:419;63057:12;:19:::0;63053:23;::::1;63033:419;;;63118:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;63098:17;;:14;;63136:1;;63098:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;63153:17:::1;::::0;::::1;63176:1;63153:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;63196:17;;:14;;63171:1;;63196:17;::::1;;;;;:::i;:::-;;;;;;;:21;63192:249;;;63238:84;63266:12;63279:1;63266:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;63283:19;63304:14;63319:1;63304:17;;;;;;;;:::i;:::-;;;;;;;63238:27;:84::i;:::-;63359:8;63348:77;;;63369:14;63384:1;63369:17;;;;;;;;:::i;:::-;;;;;;;63388:12;63401:1;63388:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;63348:77:::1;::::0;;23547:25:1;;;63388:15:0::1;::::0;;::::1;23649:18:1::0;;;23642:43;;;;23721:15;;23701:18;;;23694:43;23535:2;23520:18;63348:77:0::1;;;;;;;63192:249;63078:3;;63033:419;;;;62299:1313:::0;;;;;;;:::o;31988:361::-;32183:45;;;32172:10;20571:55:1;;;32183:45:0;;;20553:74:1;20643:18;;;;20636:34;;;32183:45:0;;;;;;;;;;20526:18:1;;;;32183:45:0;;;;;;;;;;;;;32172:57;;-1:-1:-1;;;;32172:10:0;;;;:57;;32183:45;32172:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32136:93;;;;32248:7;:57;;;;-1:-1:-1;32260:11:0;;:16;;:44;;;32291:4;32280:24;;;;;;;;;;;;:::i;:::-;32240:101;;;;;;;24492:2:1;32240:101:0;;;24474:21:1;24531:2;24511:18;;;24504:30;24570:33;24550:18;;;24543:61;24621:18;;32240:101:0;24290:355:1;32240:101:0;32058:291;;31988:361;;;:::o;94016:590::-;94098:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94098:31:0;94131:15;94163:11;;94159:347;;94196:9;94191:304;94215:28;;;;;;;:12;:28;;;;;:35;94211:39;;94191:304;;;94290:28;;;;;;;:12;:28;;;;;:31;;94319:1;;94290:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;94280:6;:48;94276:204;;94367:28;;;;;;;:12;:28;;;;;:31;;94396:1;;94367:31;;;;;;:::i;:::-;;;;;;;;;;;94352:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94431:1;94421:11;;94455:5;;94276:204;94252:3;;94191:304;;;;94159:347;94524:11;;;;;:44;;-1:-1:-1;94539:19:0;;:29;;94524:44;94516:72;;;;;;;24852:2:1;94516:72:0;;;24834:21:1;24891:2;24871:18;;;24864:30;24930:17;24910:18;;;24903:45;24965:18;;94516:72:0;24650:339:1;94516:72:0;94016:590;;;;;:::o;32357:402::-;32582:51;;;32571:10;25275:15:1;;;32582:51:0;;;25257:34:1;25327:15;;;25307:18;;;25300:43;25359:18;;;;25352:34;;;32582:51:0;;;;;;;;;;25169:18:1;;;;32582:51:0;;;;;;;;;;;;;32571:63;;-1:-1:-1;;;;32571:10:0;;;;:63;;32582:51;32571:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32535:99;;;;32653:7;:57;;;;-1:-1:-1;32665:11:0;;:16;;:44;;;32696:4;32685:24;;;;;;;;;;;;:::i;:::-;32645:106;;;;;;;25599:2:1;32645:106:0;;;25581:21:1;25638:2;25618:18;;;25611:30;25677:34;25657:18;;;25650:62;25748:6;25728:18;;;25721:34;25772:19;;32645:106:0;25397:400:1;32645:106:0;32445:314;;32357:402;;;;:::o;93131:877::-;93259:17;93279:27;93291:14;93279:11;:27::i;:::-;93259:47;;93323:6;93319:561;;;93414:3;93387:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;93432:33:0;;;;;;;:17;:33;;;;;:40;;93469:3;;93432:33;:40;;93469:3;;93432:40;:::i;:::-;;;;-1:-1:-1;;93526:23:0;;;;93522:64;;93551:28;;;;;;;:17;:28;;;;;:35;;93583:3;;93551:28;:35;;93583:3;;93551:35;:::i;:::-;;;;-1:-1:-1;;93522:64:0;93319:561;;;93696:3;93669:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;93714:33:0;;;;;;;:17;:33;;;;;:40;;93751:3;;93714:33;:40;;93751:3;;93714:40;:::i;:::-;;;;-1:-1:-1;;93808:23:0;;;;93804:64;;93833:28;;;;;;;:17;:28;;;;;:35;;93865:3;;93833:28;:35;;93865:3;;93833:35;:::i;:::-;;;;-1:-1:-1;;93804:64:0;93948:52;93972:14;93988:5;93995:4;57967:1962;58153:22;;;;;;;58148:214;;58301:8;58297:54;;;58329:6;:4;:6::i;:::-;58502:19;58498:109;;;58571:24;58587:7;58571:15;:24::i;:::-;58537:31;;;;;;;:22;:31;;;;;:58;58498:109;58631:21;;;;58627:1295;;58845:27;58891:28;58938:27;58983:30;59005:7;58983:21;:30::i;:::-;59080:22;;58823:190;;-1:-1:-1;58823:190:0;;-1:-1:-1;58823:190:0;-1:-1:-1;59080:22:0;;;;;59075:49;;59104:20;59116:7;59104:11;:20::i;:::-;59200:31;;;;;;;:22;:31;;;;;:54;;;59341:42;;;59337:572;;59404:19;59426:41;59448:19;59426;:41;:::i;:::-;59404:63;;59536:11;59511:22;;:36;;;;:::i;:::-;59486:22;:61;59595:33;59617:11;59595:19;:33;:::i;:::-;59566:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;59337:572:0;;;59669:19;59691:41;59713:19;59691;:41;:::i;:::-;59669:63;;59801:11;59776:22;;:36;;;;:::i;:::-;59751:22;:61;59860:33;59882:11;59860:19;:33;:::i;:::-;59831:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;58654:1268:0;;;57967:1962;;;:::o;63699:4846::-;63786:29;:27;:29::i;:::-;63905:9;63900:327;63924:18;:25;63920:29;;63900:327;;;63971:34;64008:18;64027:1;64008:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;64048:40:0;;64044:172;;64109:91;;;;;64194:4;64109:91;;;4231:74:1;64109:76:0;;;;;;4204:18:1;;64109:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;64044:172;-1:-1:-1;63951:3:0;;63900:327;;;;64587:27;40560:6;64643:12;;64625:15;:30;;;;:::i;:::-;64617:57;;;;:::i;:::-;64587:87;;64813:9;64808:284;64832:12;:19;64828:23;;64808:284;;;64954:12;64967:1;64954:15;;;;;;;;:::i;:::-;;;;;;;;;;;64947:48;;;;;64989:4;64947:48;;;4231:74:1;64954:15:0;;;;;64947:33;;4204:18:1;;64947:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64918:23;:19;64940:1;64918:23;:::i;:::-;40560:6;64882:14;64894:1;64882:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;64881:114;;65061:12;65074:1;65061:15;;;;;;;;:::i;:::-;;;;;;;;;;;;65004:73;;;26294:34:1;65004:73:0;;;26282:47:1;;;;26359:6;26345:12;;;26338:28;26404:2;26400:15;;;26382:12;;;26375:110;26501:12;;65004:73:0;;;;;;;;;;;;64873:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;64853:3:0;;64808:284;;;-1:-1:-1;40560:6:0;65304:23;:19;65326:1;65304:23;:::i;:::-;65303:43;;;;:::i;:::-;65287:12;;:60;;;;:::i;:::-;65272:12;:75;68508:29;68553:435;68640:34;68677:17;:15;:17::i;:::-;68640:54;;68757:9;68752:133;68776:21;:28;68772:32;;68752:133;;;68853:17;68871:1;68853:20;;;;;;;;:::i;:::-;;;;;;;68826:21;68848:1;68826:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;68806:3;;68752:133;;;;68954:26;:24;:26::i;:::-;68937:14;:43;-1:-1:-1;68553:435:0:o;59937:585::-;59999:21;;;;59995:520;;60076:27;60106:15;60113:7;60106:6;:15::i;:::-;60076:45;;60184:9;60179:118;60203:10;:17;60199:1;:21;60179:118;;;60268:10;60279:1;60268:13;;;;;;;;:::i;:::-;;;;;;;;;;;;60246:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;60222:3;;60179:118;;;;60364:9;60359:145;60383:10;:17;60379:1;:21;60359:145;;;60464:21;60486:1;60464:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;60426:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;60402:3;;60359: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;4316:260::-;4384:6;4392;4445:2;4433:9;4424:7;4420:23;4416:32;4413:52;;;4461:1;4458;4451:12;4413:52;4484:29;4503:9;4484:29;:::i;:::-;4474:39;;4532:38;4566:2;4555:9;4551:18;4532:38;:::i;:::-;4522:48;;4316:260;;;;;:::o;5004:647::-;5078:6;5086;5094;5102;5155:3;5143:9;5134:7;5130:23;5126:33;5123:53;;;5172:1;5169;5162:12;5123:53;5211:9;5198:23;5230:28;5252:5;5230:28;:::i;:::-;5277:5;-1:-1:-1;5334:2:1;5319:18;;5306:32;5347:30;5306:32;5347:30;:::i;:::-;5396:7;-1:-1:-1;5455:2:1;5440:18;;5427:32;5468:30;5427:32;5468:30;:::i;:::-;5517:7;-1:-1:-1;5576:2:1;5561:18;;5548:32;5589:30;5548:32;5589:30;:::i;:::-;5004:647;;;;-1:-1:-1;5004:647:1;;-1:-1:-1;;5004:647:1:o;5656:250::-;5741:1;5751:113;5765:6;5762:1;5759:13;5751:113;;;5841:11;;;5835:18;5822:11;;;5815:39;5787:2;5780:10;5751:113;;;-1:-1:-1;;5898:1:1;5880:16;;5873:27;5656:250::o;5911:455::-;6060:2;6049:9;6042:21;6023:4;6092:6;6086:13;6135:6;6130:2;6119:9;6115:18;6108:34;6151:79;6223:6;6218:2;6207:9;6203:18;6198:2;6190:6;6186:15;6151:79;:::i;:::-;6282:2;6270:15;6287:66;6266:88;6251:104;;;;6357:2;6247:113;;5911:455;-1:-1:-1;;5911:455:1:o;6635:254::-;6703:6;6711;6764:2;6752:9;6743:7;6739:23;6735:32;6732:52;;;6780:1;6777;6770:12;6732:52;6803:29;6822:9;6803:29;:::i;:::-;6793:39;6879:2;6864:18;;;;6851:32;;-1:-1:-1;;;6635:254:1:o;6894:315::-;6959:6;6967;7020:2;7008:9;6999:7;6995:23;6991:32;6988:52;;;7036:1;7033;7026:12;6988:52;7059:29;7078:9;7059:29;:::i;:::-;7049:39;;7138:2;7127:9;7123:18;7110:32;7151:28;7173:5;7151:28;:::i;:::-;7198:5;7188:15;;;6894:315;;;;;:::o;8439:403::-;8525:6;8533;8541;8549;8602:3;8590:9;8581:7;8577:23;8573:33;8570:53;;;8619:1;8616;8609:12;8570:53;8642:29;8661:9;8642:29;:::i;:::-;8632:39;;8718:2;8707:9;8703:18;8690:32;8680:42;;8741:38;8775:2;8764:9;8760:18;8741:38;:::i;:::-;8731:48;;8798:38;8832:2;8821:9;8817:18;8798:38;:::i;:::-;8788:48;;8439:403;;;;;;;:::o;8847:241::-;8903:6;8956:2;8944:9;8935:7;8931:23;8927:32;8924:52;;;8972:1;8969;8962:12;8924:52;9011:9;8998:23;9030:28;9052:5;9030:28;:::i;9093:184::-;9145:77;9142:1;9135:88;9242:4;9239:1;9232:15;9266:4;9263:1;9256:15;9282:915;9364:6;9417:3;9405:9;9396:7;9392:23;9388:33;9385:53;;;9434:1;9431;9424:12;9385:53;9483:7;9476:4;9465:9;9461:20;9457:34;9447:62;;9505:1;9502;9495:12;9447:62;9538:2;9532:9;9580:3;9572:6;9568:16;9650:6;9638:10;9635:22;9614:18;9602:10;9599:34;9596:62;9593:242;;;9691:77;9688:1;9681:88;9792:4;9789:1;9782:15;9820:4;9817:1;9810:15;9593:242;9851:2;9844:22;9886:6;9930:3;9915:19;;9946;;;9943:39;;;9978:1;9975;9968:12;9943:39;10002:9;10020:146;10036:6;10031:3;10028:15;10020:146;;;10104:17;;10092:30;;10151:4;10142:14;;;;10053;10020:146;;;-1:-1:-1;10185:6:1;;9282:915;-1:-1:-1;;;;;9282:915:1:o;10202:184::-;10254:77;10251:1;10244:88;10351:4;10348:1;10341:15;10375:4;10372:1;10365:15;10391:184;10443:77;10440:1;10433:88;10540:4;10537:1;10530:15;10564:4;10561:1;10554:15;10580:128;10647:9;;;10668:11;;;10665:37;;;10682:18;;:::i;10713:168::-;10786:9;;;10817;;10834:15;;;10828:22;;10814:37;10804:71;;10855:18;;:::i;10886:274::-;10926:1;10952;10942:189;;10987:77;10984:1;10977:88;11088:4;11085:1;11078:15;11116:4;11113:1;11106:15;10942:189;-1:-1:-1;11145:9:1;;10886:274::o;11165:125::-;11230:9;;;11251:10;;;11248:36;;;11264:18;;:::i;12418:184::-;12488:6;12541:2;12529:9;12520:7;12516:23;12512:32;12509:52;;;12557:1;12554;12547:12;12509:52;-1:-1:-1;12580:16:1;;12418:184;-1:-1:-1;12418:184:1:o;13664:437::-;13743:1;13739:12;;;;13786;;;13807:61;;13861:4;13853:6;13849:17;13839:27;;13807:61;13914:2;13906:6;13903:14;13883:18;13880:38;13877:218;;13951:77;13948:1;13941:88;14052:4;14049:1;14042:15;14080:4;14077:1;14070:15;16855:179;16933:13;;16986:22;16975:34;;16965:45;;16955:73;;17024:1;17021;17014:12;17039:473;17142:6;17150;17158;17166;17174;17227:3;17215:9;17206:7;17202:23;17198:33;17195:53;;;17244:1;17241;17234:12;17195:53;17267:39;17296:9;17267:39;:::i;:::-;17257:49;;17346:2;17335:9;17331:18;17325:25;17315:35;;17390:2;17379:9;17375:18;17369:25;17359:35;;17434:2;17423:9;17419:18;17413:25;17403:35;;17457:49;17501:3;17490:9;17486:19;17457:49;:::i;:::-;17447:59;;17039:473;;;;;;;;:::o;23748:287::-;23877:3;23915:6;23909:13;23931:66;23990:6;23985:3;23978:4;23970:6;23966:17;23931:66;:::i;:::-;24013:16;;;;;23748:287;-1:-1:-1;;23748:287:1:o;24040:245::-;24107:6;24160:2;24148:9;24139:7;24135:23;24131:32;24128:52;;;24176:1;24173;24166:12;24128:52;24208:9;24202:16;24227:28;24249:5;24227:28;:::i;25802:245::-;25881:6;25889;25942:2;25930:9;25921:7;25917:23;25913:32;25910:52;;;25958:1;25955;25948:12;25910:52;-1:-1:-1;;25981:16:1;;26037:2;26022:18;;;26016:25;25981:16;;26016:25;;-1:-1:-1;25802:245:1:o
Swarm Source
ipfs://1094739c3c5858a4971e25d652206dbcc4add942108dc3182acb57123271e4cc
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.