Source Code
Latest 25 from a total of 54 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Get Reward2 | 23630734 | 15 days ago | IN | 0 ETH | 0.00004766 | ||||
| Get Reward2 | 23433560 | 42 days ago | IN | 0 ETH | 0.00027497 | ||||
| Get Reward2 | 23402527 | 46 days ago | IN | 0 ETH | 0.00008049 | ||||
| Get Reward2 | 23202392 | 74 days ago | IN | 0 ETH | 0.00015152 | ||||
| Get Reward2 | 23151322 | 82 days ago | IN | 0 ETH | 0.00010968 | ||||
| Get Reward2 | 23079238 | 92 days ago | IN | 0 ETH | 0.00011803 | ||||
| Get Reward2 | 22951290 | 109 days ago | IN | 0 ETH | 0.00036728 | ||||
| Get Reward2 | 22936625 | 112 days ago | IN | 0 ETH | 0.00038927 | ||||
| Get Reward2 | 22902715 | 116 days ago | IN | 0 ETH | 0.0002877 | ||||
| Lock Additional | 22800857 | 131 days ago | IN | 0 ETH | 0.00025412 | ||||
| Get Reward2 | 22798450 | 131 days ago | IN | 0 ETH | 0.00039298 | ||||
| Get Reward2 | 22622810 | 155 days ago | IN | 0 ETH | 0.00052713 | ||||
| Get Reward2 | 22599714 | 159 days ago | IN | 0 ETH | 0.00047206 | ||||
| Get Reward2 | 22571994 | 163 days ago | IN | 0 ETH | 0.00021333 | ||||
| Stake Locked | 22522706 | 169 days ago | IN | 0 ETH | 0.00067436 | ||||
| Withdraw Locked | 22522679 | 169 days ago | IN | 0 ETH | 0.00060227 | ||||
| Get Reward2 | 22522654 | 169 days ago | IN | 0 ETH | 0.00038289 | ||||
| Get Reward2 | 22305083 | 200 days ago | IN | 0 ETH | 0.00017654 | ||||
| Get Reward2 | 22260052 | 206 days ago | IN | 0 ETH | 0.00019312 | ||||
| Get Reward2 | 22084552 | 231 days ago | IN | 0 ETH | 0.00025581 | ||||
| Get Reward2 | 22050756 | 235 days ago | IN | 0 ETH | 0.00028465 | ||||
| Get Reward2 | 21986413 | 244 days ago | IN | 0 ETH | 0.00038003 | ||||
| Get Reward2 | 21954418 | 249 days ago | IN | 0 ETH | 0.00036872 | ||||
| Get Reward2 | 21887282 | 258 days ago | IN | 0 ETH | 0.00035297 | ||||
| Get Reward2 | 21858006 | 262 days ago | IN | 0 ETH | 0.00034643 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FraxUnifiedFarm_ERC20_Other
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2024-01-10
*/
// 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/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/balancer/IAuraGauge.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IAuraGauge {
struct Reward {
address token;
address distributor;
uint256 period_finish;
uint256 rate;
uint256 last_update;
uint256 integral;
}
function deposit ( uint256 _value ) external;
function deposit ( uint256 _value, address _addr ) external;
function deposit ( uint256 _value, address _addr, bool _claim_rewards ) external;
function withdraw ( uint256 _value ) external;
function withdraw ( uint256 _value, bool _claim_rewards ) external;
function claim_rewards ( ) external;
function claim_rewards ( address _addr ) external;
function claim_rewards ( address _addr, address _receiver ) external;
function transferFrom ( address _from, address _to, uint256 _value ) external returns ( bool );
function transfer ( 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 increaseAllowance ( address _spender, uint256 _added_value ) external returns ( bool );
function decreaseAllowance ( address _spender, uint256 _subtracted_value ) external returns ( bool );
function user_checkpoint ( address addr ) external returns ( bool );
function set_rewards_receiver ( address _receiver ) external;
function kick ( address addr ) external;
function deposit_reward_token ( address _reward_token, uint256 _amount ) external;
function add_reward ( address _reward_token, address _distributor ) external;
function set_reward_distributor ( address _reward_token, address _distributor ) external;
function killGauge ( ) external;
function unkillGauge ( ) external;
function claimed_reward ( address _addr, address _token ) external view returns ( uint256 );
function claimable_reward ( address _user, address _reward_token ) external view returns ( uint256 );
function claimable_tokens ( address addr ) external returns ( uint256 );
function integrate_checkpoint ( ) external view returns ( uint256 );
function future_epoch_time ( ) external view returns ( uint256 );
function inflation_rate ( ) external view returns ( uint256 );
function decimals ( ) external view returns ( uint256 );
function version ( ) external view returns ( string memory );
function allowance ( address owner, address spender ) external view returns ( uint256 );
function initialize ( address _lp_token, uint256 relative_weight_cap ) external;
function setRelativeWeightCap ( uint256 relative_weight_cap ) external;
function getRelativeWeightCap ( ) external view returns ( uint256 );
function getCappedRelativeWeight ( uint256 time ) external view returns ( uint256 );
function getMaxRelativeWeightCap ( ) external pure returns ( uint256 );
function balanceOf ( address arg0 ) external view returns ( uint256 );
function totalSupply ( ) external view returns ( uint256 );
function name ( ) external view returns ( string memory );
function symbol ( ) external view returns ( string memory );
function DOMAIN_SEPARATOR ( ) external view returns ( bytes32 );
function nonces ( address arg0 ) external view returns ( uint256 );
function lp_token ( ) external view returns ( address );
function is_killed ( ) external view returns ( bool );
function reward_count ( ) external view returns ( uint256 );
function reward_data ( address arg0 ) external view returns ( Reward memory );
function rewards_receiver ( address arg0 ) external view returns ( address );
function reward_integral_for ( address arg0, address arg1 ) external view returns ( uint256 );
function working_balances ( address arg0 ) external view returns ( uint256 );
function working_supply ( ) external view returns ( uint256 );
function integrate_inv_supply_of ( address arg0 ) external view returns ( uint256 );
function integrate_checkpoint_of ( address arg0 ) external view returns ( uint256 );
function integrate_fraction ( address arg0 ) external view returns ( uint256 );
function period ( ) external view returns ( int128 );
function reward_tokens ( uint256 arg0 ) external view returns ( address );
function period_timestamp ( uint256 arg0 ) external view returns ( uint256 );
function integrate_inv_supply ( uint256 arg0 ) external view returns ( uint256 );
}
// File contracts/Misc_AMOs/balancer/IBalancerMinter.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IBalancerMinter {
function allowed_to_mint_for ( address minter, address user ) external view returns ( bool );
function getBalancerToken ( ) external view returns ( address );
function getBalancerTokenAdmin ( ) external view returns ( address );
function getDomainSeparator ( ) external view returns ( bytes32 );
function getGaugeController ( ) external view returns ( address );
function getMinterApproval ( address minter, address user ) external view returns ( bool );
function getNextNonce ( address user ) external view returns ( uint256 );
function mint ( address gauge ) external returns ( uint256 );
function mintFor ( address gauge, address user ) external returns ( uint256 );
function mintMany ( address[] memory gauges ) external returns ( uint256 );
function mintManyFor ( address[] memory gauges, address user ) external returns ( uint256 );
function mint_for ( address gauge, address user ) external;
function mint_many ( address[8] memory gauges ) external;
function minted ( address user, address gauge ) external view returns ( uint256 );
function setMinterApproval ( address minter, bool approval ) external;
function setMinterApprovalWithSignature ( address minter, bool approval, address user, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external;
function toggle_approve_mint ( address minter ) external;
}
// 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
// ====================
// BUNNI
// ====================
// import "../Misc_AMOs/bunni/IBunniGauge.sol";
// import "../Misc_AMOs/bunni/IBunniLens.sol";
// import "../Misc_AMOs/bunni/IBunniMinter.sol";
// CONVEX
// ====================
// import "../Misc_AMOs/convex/IConvexBaseRewardPool.sol";
contract FraxUnifiedFarmTemplate is Owned, ReentrancyGuard {
// -------------------- VARIES --------------------
// Balancer
IAuraGauge public stakingToken;
IBalancerMinter public minter = IBalancerMinter(0x239e55F427D44C3cc793f49bFB507ebe76638a2b);
// 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 = 0; // 0 sec
// 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);
// 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) {
// BAL
// ====================================
uint256 bal_before = IERC20(rewardTokens[1]).balanceOf(address(this));
minter.mint(address(stakingToken));
uint256 bal_after = IERC20(rewardTokens[1]).balanceOf(address(this));
// Set the new reward rate
rewardRatesManual[1] = (bal_after - bal_before) / rewardsDuration;
}
// 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))
) {
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) && (_misc_vars[5] >= 0), "Must be >= 0");
require((_misc_vars[4] >= 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/IAuraGauge.sol";
// Bunni
// import "../Misc_AMOs/bunni/IBunniGauge.sol";
// Convex wrappers
// import "../Curve/ICurvefrxETHETHPool.sol";
// import "../Misc_AMOs/convex/IConvexStakingWrapperFrax.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/ICurveStableSwapNG.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;
// ICurveTricryptoOptimizedWETH public curveToken;
// I2pool public curvePool;
// ICurvefrxETHETHPool public curvePool;
// ICurveStableSwapNG 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);
// 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);
// 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) {
// Give the tokens to the destination_address
// Should throw if insufficient balance
TransferHelper.safeTransfer(address(stakingToken), destination_address, liquidity);
// Remove the stake from the array
delete lockedStakes[staker_address][theArrayIndex];
// Update liquidities
_updateLiqAmts(staker_address, liquidity, false);
emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address);
}
return liquidity;
}
function _getRewardExtraLogic(address rewardee, address destination_address) internal override {
// Do nothing
}
/* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */
// Inherited...
/* ========== EVENTS ========== */
event LockedAdditional(address indexed user, bytes32 kek_id, uint256 amount);
event LockedLonger(address indexed user, bytes32 kek_id, uint256 new_secs, uint256 new_start_ts, uint256 new_end_ts);
event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address);
event WithdrawLocked(address indexed user, uint256 liquidity, bytes32 kek_id, address destination_address);
}
// File contracts/Misc_AMOs/balancer/IBalancerVault.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IBalancerVault {
function WETH () external view returns (address);
// function batchSwap (uint8 kind, tuple[] swaps, address[] assets, tuple funds, int256[] limits, uint256 deadline) external returns (int256[] assetDeltas);
function deregisterTokens (bytes32 poolId, address[] memory tokens) external;
// function exitPool (bytes32 poolId, address sender, address recipient, tuple request) external;
function flashLoan (address recipient, address[] memory tokens, uint256[] memory amounts, bytes memory userData) external;
function getActionId (bytes4 selector) external view returns (bytes32);
function getAuthorizer () external view returns (address);
function getDomainSeparator () external view returns (bytes32);
function getInternalBalance (address user, address[] memory tokens) external view returns (uint256[] memory balances);
function getNextNonce (address user) external view returns (uint256);
function getPausedState () external view returns (bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime);
function getPool (bytes32 poolId) external view returns (address, uint8);
function getPoolTokenInfo (bytes32 poolId, address token) external view returns (uint256 cash, uint256 managed, uint256 lastChangeBlock, address assetManager);
function getPoolTokens (bytes32 poolId) external view returns (address[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock);
function getProtocolFeesCollector () external view returns (address);
function hasApprovedRelayer (address user, address relayer) external view returns (bool);
// function joinPool (bytes32 poolId, address sender, address recipient, tuple request) external;
// function managePoolBalance (tuple[] ops) external;
// function manageUserBalance (tuple[] ops) external;
// function queryBatchSwap (uint8 kind, tuple[] swaps, address[] assets, tuple funds) external returns (int256[]);
function registerPool (uint8 specialization) external returns (bytes32);
function registerTokens (bytes32 poolId, address[] memory tokens, address[] memory assetManagers) external;
function setAuthorizer (address newAuthorizer) external;
function setPaused (bool paused) external;
function setRelayerApproval (address sender, address relayer, bool approved) external;
// function swap (tuple singleSwap, tuple funds, uint256 limit, uint256 deadline) external returns (uint256 amountCalculated);
}
// File contracts/Misc_AMOs/balancer/IComposableStablePool.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IComposableStablePool {
function DELEGATE_PROTOCOL_SWAP_FEES_SENTINEL ( ) external view returns ( uint256 );
function DOMAIN_SEPARATOR ( ) external view returns ( bytes32 );
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 decimals ( ) external view returns ( uint8 );
function decreaseAllowance ( address spender, uint256 amount ) external returns ( bool );
function disableRecoveryMode ( ) external;
function enableRecoveryMode ( ) external;
function getActionId ( bytes4 selector ) external view returns ( bytes32 );
function getActualSupply ( ) external view returns ( uint256 );
function getAmplificationParameter ( ) external view returns ( uint256 value, bool isUpdating, uint256 precision );
function getAuthorizer ( ) external view returns ( address );
function getBptIndex ( ) external view returns ( uint256 );
function getDomainSeparator ( ) external view returns ( bytes32 );
function getLastJoinExitData ( ) external view returns ( uint256 lastJoinExitAmplification, uint256 lastPostJoinExitInvariant );
function getMinimumBpt ( ) external pure returns ( uint256 );
function getNextNonce ( address account ) external view returns ( uint256 );
function getOwner ( ) external view returns ( address );
function getPausedState ( ) external view returns ( bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime );
function getPoolId ( ) external view returns ( bytes32 );
function getProtocolFeePercentageCache ( uint256 feeType ) external view returns ( uint256 );
function getProtocolFeesCollector ( ) external view returns ( address );
function getProtocolSwapFeeDelegation ( ) external view returns ( bool );
function getRate ( ) external view returns ( uint256 );
function getRateProviders ( ) external view returns ( address[] memory );
function getScalingFactors ( ) external view returns ( uint256[] memory );
function getSwapFeePercentage ( ) external view returns ( uint256 );
function getTokenRate ( address token ) external view returns ( uint256 );
function getTokenRateCache ( address token ) external view returns ( uint256 rate, uint256 oldRate, uint256 duration, uint256 expires );
function getVault ( ) external view returns ( address );
function inRecoveryMode ( ) external view returns ( bool );
function increaseAllowance ( address spender, uint256 addedValue ) external returns ( bool );
function isExemptFromYieldProtocolFee ( ) external view returns ( bool );
function isTokenExemptFromYieldProtocolFee ( address token ) external view returns ( bool );
function name ( ) external view returns ( string memory );
function nonces ( address owner ) external view returns ( uint256 );
function onExitPool ( bytes32 poolId, address sender, address recipient, uint256[] memory balances, uint256 lastChangeBlock, uint256 protocolSwapFeePercentage, bytes memory userData ) external returns ( uint256[] memory, uint256[] memory );
function onJoinPool ( bytes32 poolId, address sender, address recipient, uint256[] memory balances, uint256 lastChangeBlock, uint256 protocolSwapFeePercentage, bytes memory userData ) external returns ( uint256[] memory, uint256[] memory );
function pause ( ) external;
function permit ( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external;
function queryExit ( bytes32 poolId, address sender, address recipient, uint256[] memory balances, uint256 lastChangeBlock, uint256 protocolSwapFeePercentage, bytes memory userData ) external returns ( uint256 bptIn, uint256[] memory amountsOut );
function queryJoin ( bytes32 poolId, address sender, address recipient, uint256[] memory balances, uint256 lastChangeBlock, uint256 protocolSwapFeePercentage, bytes memory userData ) external returns ( uint256 bptOut, uint256[] memory amountsIn );
function setAssetManagerPoolConfig ( address token, bytes memory poolConfig ) external;
function setSwapFeePercentage ( uint256 swapFeePercentage ) external;
function setTokenRateCacheDuration ( address token, uint256 duration ) external;
function startAmplificationParameterUpdate ( uint256 rawEndValue, uint256 endTime ) external;
function stopAmplificationParameterUpdate ( ) external;
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 );
function unpause ( ) external;
function updateProtocolFeePercentageCache ( ) external;
function updateTokenRateCache ( address token ) external;
function version ( ) external view returns ( string memory );
}
// 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_Other.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
// Balancer
// =========================
// Bunni
// =========================
// import "../../Misc_AMOs/bunni/IBunniTokenLP.sol";
// import "../../Misc_AMOs/bunni/IBunniGauge.sol";
// import "../../Misc_AMOs/bunni/IBunniLens.sol";
// import "../../Misc_AMOs/bunni/IBunniMinter.sol";
// import "../../Uniswap_V3/IUniswapV3Pool.sol";
contract FraxUnifiedFarm_ERC20_Other is FraxUnifiedFarm_ERC20 {
// frxETH Pricing
AggregatorV3Interface internal priceFeedETHUSD = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
// Balancer
IComposableStablePool public lp_tkn;
IBalancerVault public vault;
// Bunni
// IBunniTokenLP public lp_tkn;
// IUniswapV3Pool public univ3_pool;
string public farm_type = "ERC20_Convex_Other";
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
// Balancer
stakingToken = IAuraGauge(_stakingToken);
lp_tkn = IComposableStablePool(stakingToken.lp_token());
vault = IBalancerVault(lp_tkn.getVault());
// Bunni
// stakingToken = IBunniGauge(_stakingToken);
// lp_tkn = IBunniTokenLP(stakingToken.lp_token());
// univ3_pool = IUniswapV3Pool(lp_tkn.pool());
// address token0 = univ3_pool.token0();
// frax_is_token0 = (token0 == frax_address);
}
// Balancer
// ----------------------------------------
function setBalancerAddrs(address _minter, address _vault) public onlyByOwnGov {
minter = IBalancerMinter(_minter);
vault = IBalancerVault(_vault);
}
// In case the rewards get screwed up
function toggleBalancer3rdPartyBalClaimer(address _claimer) public onlyByOwnGov {
minter.toggle_approve_mint(_claimer);
}
// Bunni
// ----------------------------------------
// function setBunniAddrs(address _lens, address _minter) public onlyByOwnGov {
// lens = IBunniLens(_lens);
// minter = IBunniMinter(_minter);
// }
// // In case the rewards get screwed up
// function toggleBunni3rdPartyOLITClaimer(address _claimer) public onlyByOwnGov {
// minter.toggle_approve_mint(_claimer);
// }
// frxETH pricing
// ----------------------------------------
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
// Balancer frxETH-pETH Gauge
// ============================================
{
// Get the pool ID
bytes32 _poolId = lp_tkn.getPoolId();
// Get the balances of each token in the pool
( , uint256[] memory balances, ) = vault.getPoolTokens(_poolId);
uint256 frxETH_in_pool = balances[1];
uint256 frxETH_usd_value_e36 = (1e10) * (frxETH_in_pool * uint256(getLatestETHPriceE8()));
// Calculate the frxETH value per "actual" LP
frax_per_lp_token = (frxETH_usd_value_e36) / lp_tkn.getActualSupply();
}
// Bunni FRAX/USDC Gauge
// ============================================
// {
// // Get the BunniKey so you can query the lens
// IBunniLens.BunniKey memory bkey = IBunniLens.BunniKey({
// pool: univ3_pool,
// tickLower: lp_tkn.tickLower(),
// tickUpper: lp_tkn.tickUpper()
// });
// (, uint256 amt0, uint256 amt1) = lens.pricePerFullShare(bkey);
// // Calc FRAX per LP
// if (frax_is_token0) frax_per_lp_token = amt0;
// else frax_per_lp_token = amt1;
// }
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":[{"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":[],"name":"lp_tkn","outputs":[{"internalType":"contract IComposableStablePool","name":"","type":"address"}],"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":[],"name":"minter","outputs":[{"internalType":"contract IBalancerMinter","name":"","type":"address"}],"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":"_minter","type":"address"},{"internalType":"address","name":"_vault","type":"address"}],"name":"setBalancerAddrs","outputs":[],"stateMutability":"nonpayable","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 IAuraGauge","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":"_claimer","type":"address"}],"name":"toggleBalancer3rdPartyBalClaimer","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":[],"name":"vault","outputs":[{"internalType":"contract IBalancerVault","name":"","type":"address"}],"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
600480546001600160a01b03191673239e55f427d44c3cc793f49bfb507ebe76638a2b179055671bc16d674ec8000060088190556305a39a806009556000600a55673782dace9d900000600b819055600c91909155600d5560c06040526005608090815264189718171b60d91b60a0526025906200007e90826200070e565b50602880546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b841917905560408051808201909152601281527122a92199182fa1b7b73b32bc2fa7ba3432b960711b6020820152602b90620000dd90826200070e565b50348015620000eb57600080fd5b5060405162006984380380620069848339810160408190526200010e9162000936565b86868686868686868686868686856001600160a01b038116620001775760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15060016002558451620001e9906012906020880190620005a8565b508151620001ff906013906020850190620005a8565b50805162000215906014906020840190620005a8565b5082516200022b90601590602086019062000612565b5060005b8551811015620003df57806017600088848151811062000253576200025362000a3d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506001601660008884815181106200029a576200029a62000a3d565b6020908102919091018101516001600160a01b031682528101919091526040016000908120805460ff191692151592909217909155601880546001810182559082527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0155845185908290811062000316576200031662000a3d565b60200260200101516011600088848151811062000337576200033762000a3d565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601c805460018181019092557f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a21101829055601d805480830182559083527f6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146134f0191909155016200022f565b506024805460ff19169055426007556040805163513872bd60e01b81529051733669c421b77340b2979d1a00a792cc2ee0fce7379163513872bd9160048083019260209291908290030181865afa1580156200043f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000465919062000a53565b6006555050600380546001600160a01b0319166001600160a01b038e1690811790915560408051634163183360e11b81529051919c506382c630669b5060048082019b5060209a509198508890030195508694508a93505050505afa158015620004d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004f9919062000a6d565b602980546001600160a01b0319166001600160a01b03929092169182179055604080516311b2515f60e31b81529051638d928af8916004808201926020929091908290030181865afa15801562000554573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200057a919062000a6d565b602a80546001600160a01b0319166001600160a01b03929092169190911790555062000a9295505050505050565b82805482825590600052602060002090810192821562000600579160200282015b828111156200060057825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620005c9565b506200060e92915062000650565b5090565b82805482825590600052602060002090810192821562000600579160200282015b828111156200060057825182559160200191906001019062000633565b5b808211156200060e576000815560010162000651565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200069257607f821691505b602082108103620006b357634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000709576000816000526020600020601f850160051c81016020861015620006e45750805b601f850160051c820191505b818110156200070557828155600101620006f0565b5050505b505050565b81516001600160401b038111156200072a576200072a62000667565b62000742816200073b84546200067d565b84620006b9565b602080601f8311600181146200077a5760008415620007615750858301515b600019600386901b1c1916600185901b17855562000705565b600085815260208120601f198616915b82811015620007ab578886015182559484019460019091019084016200078a565b5085821015620007ca5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b0381168114620007f257600080fd5b919050565b604051601f8201601f191681016001600160401b038111828210171562000822576200082262000667565b604052919050565b60006001600160401b0382111562000846576200084662000667565b5060051b60200190565b600082601f8301126200086257600080fd5b815160206200087b62000875836200082a565b620007f7565b8083825260208201915060208460051b8701019350868411156200089e57600080fd5b602086015b84811015620008c557620008b781620007da565b8352918301918301620008a3565b509695505050505050565b600082601f830112620008e257600080fd5b81516020620008f562000875836200082a565b8083825260208201915060208460051b8701019350868411156200091857600080fd5b602086015b84811015620008c557805183529183019183016200091d565b600080600080600080600060e0888a0312156200095257600080fd5b6200095d88620007da565b60208901519097506001600160401b03808211156200097b57600080fd5b620009898b838c0162000850565b975060408a0151915080821115620009a057600080fd5b620009ae8b838c0162000850565b965060608a0151915080821115620009c557600080fd5b620009d38b838c01620008d0565b955060808a0151915080821115620009ea57600080fd5b620009f88b838c0162000850565b945060a08a015191508082111562000a0f57600080fd5b5062000a1e8a828b0162000850565b92505062000a2f60c08901620007da565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a6657600080fd5b5051919050565b60006020828403121562000a8057600080fd5b62000a8b82620007da565b9392505050565b615ee28062000aa26000396000f3fe608060405234801561001057600080fd5b50600436106104c25760003560e01c80637f472e5411610286578063cdc82e801161016b578063e1ba95d2116100e3578063f2caeb1e11610097578063facefb641161007c578063facefb6414610af4578063fbfa77cf14610b07578063fff6cae914610b2757600080fd5b8063f2caeb1e14610ace578063f77e34d114610ae157600080fd5b8063ebe2b12b116100c8578063ebe2b12b14610ab3578063f288baf614610abc578063f2a8d34914610ac557600080fd5b8063e1ba95d214610a98578063e7f3058214610aa057600080fd5b8063d5e1a9c61161013a578063d9f96e8d1161011f578063d9f96e8d14610a48578063de1a655114610a7d578063e01f62bf14610a9057600080fd5b8063d5e1a9c614610a22578063d7400d5614610a3557600080fd5b8063cdc82e80146109ea578063d2010fb4146109f3578063d2fbdc0d146109fc578063d42fc9b414610a0f57600080fd5b8063aa1d4fce116101fe578063bdb123e3116101cd578063c3543826116101b2578063c354382614610998578063c8f33c91146109ab578063ca6df29d146109b457600080fd5b8063bdb123e31461097d578063c00007b01461098557600080fd5b8063aa1d4fce14610945578063af48e59a1461094e578063b85efd0614610961578063b94c4dcb1461097457600080fd5b80638da5cb5b116102555780639637927f1161023a5780639637927f14610912578063a0f234761461091f578063a321ff971461093257600080fd5b80638da5cb5b146108df57806391cf600a146108ff57600080fd5b80637f472e54146108765780638980f11f1461088957806389b5f00b1461089c5780638bad86a7146108b157600080fd5b806341a16f3f116103ac5780636e27cef911610324578063774d4ae7116102f35780637970833e116102d85780637970833e1461081357806379ba50971461084e5780637d6ef08e1461085657600080fd5b8063774d4ae7146107ed5780637910d17b1461080057600080fd5b80636e27cef9146107a957806370641a36146107b257806372f702f3146107ba578063741d3c18146107da57600080fd5b806354fd4d501161037b57806364f2c0601161036057806364f2c0601461076157806369339245146107695780636c430dbb1461078957600080fd5b806354fd4d50146107515780635bfd92581461075957600080fd5b806341a16f3f146106d357806341edbdf0146107095780634fd2b5361461071e57806353a47bb71461073157600080fd5b80631face8561161043f5780632c0c2a0a1161040e57806336f89af2116103f357806336f89af214610680578063386a9525146106b6578063387edc86146106c057600080fd5b80632c0c2a0a1461065a5780632df079f11461066d57600080fd5b80631face856146105ce578063231b68dc146105e15780632352aac11461060457806328408bab1461062457600080fd5b806312edb24c1161049657806317b18c891161047b57806317b18c89146105935780631c1f78eb146105a65780631e090f01146105ae57600080fd5b806312edb24c146105695780631627540c1461057e57600080fd5b80628cc262146104c75780630238b936146104f057806307546172146105115780630d7bac4f14610556575b600080fd5b6104da6104d53660046156db565b610b2f565b6040516104e791906156f8565b60405180910390f35b6105036104fe36600461574a565b610ca4565b6040519081526020016104e7565b6004546105319073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104e7565b61050361056436600461578c565b610da5565b610571610dd1565b6040516104e791906157a5565b61059161058c3660046156db565b610e40565b005b6105036105a13660046157f3565b610f60565b6104da610fea565b6105c16105bc3660046156db565b611081565b6040516104e79190615815565b6105036105dc3660046156db565b611135565b6105f46105ef366004615883565b61117b565b60405190151581526020016104e7565b6029546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6105316106323660046156db565b60236020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6105036106683660046156db565b611261565b61059161067b3660046158bc565b61154d565b61050361068e3660046156db565b73ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205490565b61050362093a8081565b6105916106ce3660046156db565b6116c6565b6105316106e13660046156db565b60116020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b610711611825565b6040516104e7919061593c565b61050361072c3660046156db565b6118b3565b6001546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6107116118d4565b6105036118e1565b601f54610503565b6105036107773660046156db565b60176020526000908152604090205481565b6105036107973660046156db565b601b6020526000908152604090205481565b610503600a5481565b6104da611b1c565b6003546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6105916107e83660046156db565b611c71565b6105036107fb36600461598d565b611dd4565b6104da61080e3660046159b9565b611fe0565b61082661082136600461598d565b61205c565b604080519586526020860194909452928401919091526060830152608082015260a0016104e7565b6105916120aa565b6105036108643660046156db565b60226020526000908152604090205481565b6105036108843660046156db565b6121f5565b61059161089736600461598d565b61220c565b6024546105f490640100000000900460ff1681565b6108c46108bf3660046156db565b61239d565b604080519384526020840192909252908201526060016104e7565b6000546105319073ffffffffffffffffffffffffffffffffffffffff1681565b61059161090d3660046156db565b6125c9565b6024546105f49060ff1681565b61050361092d3660046156db565b6126bc565b6105916109403660046156db565b612786565b610503600b5481565b61059161095c366004615883565b6128af565b61059161096f3660046157f3565b6129a1565b61050360095481565b610503612c38565b6104da6109933660046156db565b612d7d565b6105316109a63660046156db565b612e05565b61050360075481565b6105036109c23660046156db565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b61050360085481565b61050360055481565b610591610a0a3660046157f3565b612e68565b610503610a1d3660046156db565b6132b5565b610591610a303660046159e7565b6132f0565b610591610a433660046156db565b6134df565b610503610a563660046156db565b73ffffffffffffffffffffffffffffffffffffffff16600090815260208052604090205490565b610591610a8b366004615883565b6136fa565b601e54610503565b6105916137e1565b610591610aae3660046156db565b6138b2565b61050360065481565b610503600c5481565b610503600d5481565b610503610adc36600461578c565b613a13565b610591610aef366004615a2f565b613b2a565b610591610b02366004615aca565b613cf6565b602a546105319073ffffffffffffffffffffffffffffffffffffffff1681565b610591613ea5565b60606000610b3b611b1c565b60125490915067ffffffffffffffff811115610b5957610b59615a4c565b604051908082528060200260200182016040528015610b82578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff841660009081526021602052604090205490925015610c9e5760005b601254811015610c9c5773ffffffffffffffffffffffffffffffffffffffff84166000818152601a60209081526040808320858452825280832054938352601982528083208584529091529020548351670de0b6b3a76400009190859085908110610c2157610c21615b48565b6020026020010151610c339190615ba6565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260216020526040902054610c639190615bb9565b610c6d9190615bd0565b610c779190615c0b565b838281518110610c8957610c89615b48565b6020908102919091010152600101610bb4565b505b50919050565b60006002805403610d16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602454610100900460ff1615610d8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610d0d565b610d9833848685613f4a565b6001600255949350505050565b600854600954600091610dcb91610dbc8286615bb9565b610dc69190615bd0565b614104565b92915050565b60606012805480602002602001604051908101604052809291908181526020018280548015610e3657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e0b575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ee7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610d0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610fcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055610fde338085854261411c565b60016002559392505050565b60155460609067ffffffffffffffff81111561100857611008615a4c565b604051908082528060200260200182016040528015611031578160200160208202803683370190505b50905060005b60155481101561107d5762093a8061104e82613a13565b6110589190615bb9565b82828151811061106a5761106a615b48565b6020908102919091010152600101611037565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561112a57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906110c6565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260226020526040812054600554670de0b6b3a76400009161117191615bb9565b610dcb9190615bd0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526016602052604081205460ff166111b057506000610dcb565b73ffffffffffffffffffffffffffffffffffffffff831615806111e7575073ffffffffffffffffffffffffffffffffffffffff8216155b156111f457506000610dcb565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361121f57506001610dcb565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526011602052604090205481851691160361125857506001610dcb565b50600092915050565b6000808061126e84612e05565b905073ffffffffffffffffffffffffffffffffffffffff811615611333576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e9190615c1e565b6113d5565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156113b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d59190615c1e565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615c1e565b61146f9190615bb9565b600b54600c5461147f9086615bb9565b6114899190615bb9565b6114939190615bd0565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156114c2576114bd846121f5565b6114cb565b6114cb876118b3565b9050801561151d576000816114e8670de0b6b3a764000088615bb9565b6114f29190615bd0565b9050670de0b6b3a7640000600c548261150b9190615bb9565b6115159190615bd0565b925050611522565b600091505b508082116115305780611532565b815b9450600c5485111561154457600c5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806115865750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6115ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff16620100008415150217905580801561168b5750602454640100000000900460ff16155b156116c057602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b6002805403611731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055602454640100000000900460ff16156117aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b60245462010000900460ff161561181d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d0d565b506001600255565b602b805461183290615c37565b80601f016020809104026020016040519081016040528092919081815260200182805461185e90615c37565b80156118ab5780601f10611880576101008083540402835291602001916118ab565b820191906000526020600020905b81548152906001019060200180831161188e57829003601f168201915b505050505081565b6000670de0b6b3a7640000600d546118ca846132b5565b6111719190615bb9565b6025805461183290615c37565b600080602960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338fff2d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190615c1e565b602a546040517ff94d46680000000000000000000000000000000000000000000000000000000081526004810183905291925060009173ffffffffffffffffffffffffffffffffffffffff9091169063f94d466890602401600060405180830381865afa1580156119ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a309190810190615d17565b50915050600081600181518110611a4957611a49615b48565b602002602001015190506000611a5d612c38565b611a679083615bb9565b611a76906402540be400615bb9565b9050602960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663876f303b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b099190615c1e565b611b139082615bd0565b94505050505090565b6060601e5460001480611b2f5750601f54155b15611b89576018805480602002602001604051908101604052809291908181526020018280548015610e3657602002820191906000526020600020905b815481526020019060010190808311611b6c575050505050905090565b60125467ffffffffffffffff811115611ba457611ba4615a4c565b604051908082528060200260200182016040528015611bcd578160200160208202803683370190505b50905060005b60185481101561107d57601f54611be982613a13565b600754611bf46144d9565b611bfe9190615ba6565b611c089190615bb9565b611c1a90670de0b6b3a7640000615bb9565b611c249190615bd0565b60188281548110611c3757611c37615b48565b9060005260206000200154611c4c9190615c0b565b828281518110611c5e57611c5e615b48565b6020908102919091010152600101611bd3565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611caa5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff8116611d8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610d0d565b602880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611e0e57611e0e615b48565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff89168552601b9092528320549193501115611e8c57506020810151611eb4565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601b60205260409020545b42826060015111611f7457606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601b60205260409020541015611f6b576000818360600151611f029190615ba6565b90506000836060015142611f169190615ba6565b90506000611f28610564600285615bd0565b90506000611f368382615bb9565b611f408584615bb9565b611f4a9190615c0b565b9050611f568385615c0b565b611f609082615bd0565b965050505050611fc4565b60009250611fc4565b600080828460600151611f879190615ba6565b90506000428560600151611f9b9190615ba6565b90506002611fa98284615c0b565b611fb39190615bd0565b92505050611fc081610da5565b9350505b8160800151831115611fd857816080015192505b505092915050565b6060600280540361204d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055610fde3384846144ec565b6027602052816000526040600020818154811061207857600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314612151576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610d0d565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600d546118ca84611135565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806122395750612239338261117b565b61229f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526016602052604090205460ff168080156122fb575073ffffffffffffffffffffffffffffffffffffffff8481166000908152601160205260409020541633145b80612326575080158015612326575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15612336576116c0843385614825565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610d0d565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526021602052604081205490806123ce84611261565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260208052604081205491935090158015612427575073ffffffffffffffffffffffffffffffffffffffff8516600090815260216020526040902054155b80612457575073ffffffffffffffffffffffffffffffffffffffff85166000908152600e60205260409020548310155b156124635750816124a3565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600e60205260409020546002906124969085615c0b565b6124a09190615bd0565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156125c05773ffffffffffffffffffffffffffffffffffffffff8616600090815260276020526040812080548390811061250e5761250e615b48565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006125678884611dd4565b60408301519091506000670de0b6b3a76400006125848785615c0b565b61258e9084615bb9565b6125989190615bd0565b6125a29083615c0b565b90506125ae8188615c0b565b965050600190930192506124aa915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806126025750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff166000908152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600554600d546126ce9190615bb9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277c9190615c1e565b6118ca9190615bb9565b60005473ffffffffffffffffffffffffffffffffffffffff163314806127bf5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612825576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b600480546040517fdd289d6000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481169382019390935291169063dd289d6090602401600060405180830381600087803b15801561289457600080fd5b505af11580156128a8573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806128e85750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61294e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b6004805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617909155602a8054929093169116179055565b6002805403612a0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b600280556024546301000000900460ff1615612a84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b602454640100000000900460ff1615612af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b612b05333360016144ec565b50600080612b13338561498e565b915091506000838360400151612b299190615c0b565b9050600354612b509073ffffffffffffffffffffffffffffffffffffffff16333087614b5c565b6040805160a081018252868152602085810151818301528183018490526060808701519083015260808087015190830152336000908152602790915291909120805484908110612ba257612ba2615b48565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612bf133856001614cfa565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd19190615dff565b94509450509350935060008312158015612cea57508115155b8015612d0e57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b612d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610d0d565b50909392505050565b60606002805403612dea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055612dfa338360016144ec565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f602052604081205460ff1615612e37575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602360205260409020541690565b919050565b6002805403612ed3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b600280556024546301000000900460ff1615612f4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b602454640100000000900460ff1615612fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b612fcc333360016144ec565b50600080612fda338561498e565b91509150428311613047576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610d0d565b60004283606001511161305b57600061306b565b42836060015161306b9190615ba6565b905060006130794286615ba6565b90508181116130e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610d0d565b600a54811015613150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d0d565b6009548111156131bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d0d565b6040518060a00160405280878152602001428152602001856040015181526020018681526020016131ec83610da5565b905233600090815260276020526040902080548590811061320f5761320f615b48565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505061325f3360006001614e69565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600554670de0b6b3a76400009161117191615bb9565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061331d575061331d338261117b565b613383576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601760205260409020546015805486929081106133be576133be615b48565b9060005260206000200181905550826013601760008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548154811061341f5761341f615b48565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94851617905591871681526017909152604090205460148054849290811061349057613490615b48565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f602052604090205460ff1661356e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260106020908152604080832033845290915290205460ff16613608576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610d0d565b3360009081526023602052604090205473ffffffffffffffffffffffffffffffffffffffff16801561367c57336000908152602080805260408083205473ffffffffffffffffffffffffffffffffffffffff8516845260229092528220805491929091613676908490615ba6565b90915550505b33600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915582805281842054908452602290925282208054919290916136f1908490615c0b565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806137275750613727338261117b565b61378d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b5073ffffffffffffffffffffffffffffffffffffffff918216600090815260116020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061381a5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600f602052604090205460ff1661392b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d0d565b33600081815260106020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603613a105773ffffffffffffffffffffffffffffffffffffffff8116600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690558180528083205433845260229092528220805491929091613a0a908490615ba6565b90915550505b50565b60008060138381548110613a2957613a29615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015613b0457670de0b6b3a7640000601c8481548110613a6f57613a6f615b48565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae99190615c1e565b613af39190615bb9565b613afd9190615bd0565b9150610c9e565b60158381548110613b1757613b17615b48565b9060005260206000200154915050919050565b60005b601354811015613cf257600060138281548110613b4c57613b4c615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015613ce9578280613b9e5750601d8281548110613b9057613b90615b48565b906000526020600020015442115b15613ce9576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c399190615c1e565b601c8381548110613c4c57613c4c615b48565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc99190615c1e565b601d8381548110613cdc57613cdc615b48565b6000918252602090912001555b50600101613b2d565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480613d2f5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613d95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b8051670de0b6b3a76400001115613e08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610d0d565b608081015160011115613e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610d0d565b80516008556020810151600c556040810151600d556060810151600b55608081015160095560a00151600a55565b602454640100000000900460ff1615613f1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b613f246000613b2a565b613f2c6118e1565b6005556006544210613f4257613f40614fe8565b565b613f40615564565b602454600090640100000000900460ff16613f6d57613f6b858560016144ec565b505b600080613f7a878661498e565b91509150816060015142101580613f98575060245460ff1615156001145b613ffe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610d0d565b604082015180156140f95760035461402d9073ffffffffffffffffffffffffffffffffffffffff168883614825565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260276020526040902080548390811061406457614064615b48565b60009182526020822060059091020181815560018101829055600281018290556003810182905560040181905561409e9089908390614cfa565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b60008183106141135781614115565b825b9392505050565b600085600161412d82826000614e69565b602454640100000000900460ff16156141a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b6024546301000000900460ff1615614216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b600a54851015614282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d0d565b6009548511156142ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d0d565b6003546143139073ffffffffffffffffffffffffffffffffffffffff16883089614b5c565b600061431e86610da5565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152602080805260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b9052909250906060810161440f8a8a615c0b565b8152602090810185905282546001818101855560009485529382902083516005909202019081559082015181840155604082015160028201556060820151600382015560809091015160049091015561446b908b908a90614cfa565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006144e742600654614104565b905090565b60608360016144fd82826000614e69565b602454640100000000900460ff1615614572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b60245462010000900460ff16156145e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff86166000908152601b6020526040902042905560125467ffffffffffffffff81111561462857614628615a4c565b604051908082528060200260200182016040528015614651578160200160208202803683370190505b50925060005b60125481101561481b5773ffffffffffffffffffffffffffffffffffffffff87166000908152601a6020908152604080832084845290915290205484518590839081106146a6576146a6615b48565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff88166000908152601a8252604080822084835290925290812081905584518590839081106146fa576146fa615b48565b60200260200101511115614813576147696012828154811061471e5761471e615b48565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061475c5761475c615b48565b6020026020010151614825565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff8583815181106147b3576147b3615b48565b6020026020010151601284815481106147ce576147ce615b48565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101614657565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916148bc9190615e4f565b6000604051808303816000865af19150503d80600081146148f9576040519150601f19603f3d011682016040523d82523d6000602084013e6148fe565b606091505b50915091508180156149285750805115806149285750808060200190518101906149289190615e6b565b6128a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610d0d565b6149c36040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b60008215614ae05760005b73ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902054811015614ade5773ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020805482908110614a3257614a32615b48565b9060005260206000209060050201600001548403614ad65773ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020805482908110614a8157614a81615b48565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614ade565b6001016149ce565b505b8215801590614aef5750815183145b614b55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610d0d565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691614bfb9190615e4f565b6000604051808303816000865af19150503d8060008114614c38576040519150601f19603f3d011682016040523d82523d6000602084013e614c3d565b606091505b5091509150818015614c67575080511580614c67575080806020019051810190614c679190615e6b565b614cf2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610d0d565b505050505050565b6000614d0584612e05565b90508115614db95782601e6000828254614d1f9190615c0b565b909155505073ffffffffffffffffffffffffffffffffffffffff8416600090815260208052604081208054859290614d58908490615c0b565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614db45773ffffffffffffffffffffffffffffffffffffffff811660009081526022602052604081208054859290614dae908490615c0b565b90915550505b614e60565b82601e6000828254614dcb9190615ba6565b909155505073ffffffffffffffffffffffffffffffffffffffff8416600090815260208052604081208054859290614e04908490615ba6565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614e605773ffffffffffffffffffffffffffffffffffffffff811660009081526022602052604081208054859290614e5a908490615ba6565b90915550505b6116c084600060015b602454640100000000900460ff16614e89578115614e8957614e89613ea5565b8015614ebf57614e9883611261565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600e60205260409020555b73ffffffffffffffffffffffffffffffffffffffff831615612398576000806000614ee98661239d565b6024549295509093509150640100000000900460ff16614f0c57614f0c866155cd565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600e60205260409020829055828110614f90576000614f478483615ba6565b905080601f54614f579190615c0b565b601f55614f648185615c0b565b73ffffffffffffffffffffffffffffffffffffffff881660009081526021602052604090205550614cf2565b6000614f9c8285615ba6565b905080601f54614fac9190615ba6565b601f55614fb98185615ba6565b73ffffffffffffffffffffffffffffffffffffffff881660009081526021602052604090205550505050505050565b614ff0615564565b60005b6014548110156150d75760006014828154811061501257615012615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156150ce576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af11580156150a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150cb9190615e88565b50505b50600101614ff3565b50600062093a80600654426150ec9190615ba6565b6150f69190615bd0565b905060005b6012548110156152cf576012818154811061511857615118615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561518f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151b39190615c1e565b6151be836001615c0b565b62093a806151cb84613a13565b6151d59190615bb9565b6151df9190615bb9565b1115601282815481106151f4576151f4615b48565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166044820152605801604051602081830303815290604052906152c6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0d919061593c565b506001016150fb565b5062093a806152df826001615c0b565b6152e99190615bb9565b6006546152f69190615c0b565b60065560158054600190811061530e5761530e615b48565b9060005260206000200154600014615560576000601260018154811061533657615336615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156153ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153d19190615c1e565b600480546003546040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216938101939093529293509190911690636a627842906024016020604051808303816000875af115801561544d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906154719190615c1e565b506000601260018154811061548857615488615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156154ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906155239190615c1e565b905062093a806155338383615ba6565b61553d9190615bd0565b601560018154811061555157615551615b48565b60009182526020909120015550505b613a105b600061556e611b1c565b905060005b6018548110156155be5781818151811061558f5761558f615b48565b6020026020010151601882815481106155aa576155aa615b48565b600091825260209091200155600101615573565b506155c76144d9565b60075550565b73ffffffffffffffffffffffffffffffffffffffff811615613a105760006155f482610b2f565b905060005b81518110156156585781818151811061561457615614615b48565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601a8352604080822085835290935291909120556001016155f9565b5060005b8151811015612398576018818154811061567857615678615b48565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260198252604080842085855290925291205560010161565c565b73ffffffffffffffffffffffffffffffffffffffff81168114613a1057600080fd5b6000602082840312156156ed57600080fd5b8135614115816156b9565b6020808252825182820181905260009190848201906040850190845b8181101561573057835183529284019291840191600101615714565b50909695505050505050565b8015158114613a1057600080fd5b60008060006060848603121561575f57600080fd5b833592506020840135615771816156b9565b915060408401356157818161573c565b809150509250925092565b60006020828403121561579e57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561573057835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016157c1565b6000806040838503121561580657600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b828110156158765781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101615832565b5091979650505050505050565b6000806040838503121561589657600080fd5b82356158a1816156b9565b915060208301356158b1816156b9565b809150509250929050565b600080600080608085870312156158d257600080fd5b84356158dd8161573c565b935060208501356158ed8161573c565b925060408501356158fd8161573c565b9150606085013561590d8161573c565b939692955090935050565b60005b8381101561593357818101518382015260200161591b565b50506000910152565b602081526000825180602084015261595b816040850160208701615918565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156159a057600080fd5b82356159ab816156b9565b946020939093013593505050565b600080604083850312156159cc57600080fd5b82356159d7816156b9565b915060208301356158b18161573c565b600080600080608085870312156159fd57600080fd5b8435615a08816156b9565b9350602085013592506040850135615a1f816156b9565b9150606085013561590d816156b9565b600060208284031215615a4157600080fd5b81356141158161573c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715615ac257615ac2615a4c565b604052919050565b600060c08284031215615adc57600080fd5b82601f830112615aeb57600080fd5b60405160c0810181811067ffffffffffffffff82111715615b0e57615b0e615a4c565b6040528060c0840185811115615b2357600080fd5b845b81811015615b3d578035835260209283019201615b25565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610dcb57610dcb615b77565b8082028115828204841417610dcb57610dcb615b77565b600082615c06577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610dcb57610dcb615b77565b600060208284031215615c3057600080fd5b5051919050565b600181811c90821680615c4b57607f821691505b602082108103610c9e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600067ffffffffffffffff821115615c9e57615c9e615a4c565b5060051b60200190565b600082601f830112615cb957600080fd5b81516020615cce615cc983615c84565b615a7b565b8083825260208201915060208460051b870101935086841115615cf057600080fd5b602086015b84811015615d0c5780518352918301918301615cf5565b509695505050505050565b600080600060608486031215615d2c57600080fd5b835167ffffffffffffffff80821115615d4457600080fd5b818601915086601f830112615d5857600080fd5b81516020615d68615cc983615c84565b82815260059290921b8401810191818101908a841115615d8757600080fd5b948201945b83861015615dae578551615d9f816156b9565b82529482019490820190615d8c565b91890151919750909350505080821115615dc757600080fd5b50615dd486828701615ca8565b925050604084015190509250925092565b805169ffffffffffffffffffff81168114612e6357600080fd5b600080600080600060a08688031215615e1757600080fd5b615e2086615de5565b9450602086015193506040860151925060608601519150615e4360808701615de5565b90509295509295909350565b60008251615e61818460208701615918565b9190910192915050565b600060208284031215615e7d57600080fd5b81516141158161573c565b60008060408385031215615e9b57600080fd5b50508051602090910151909290915056fea2646970667358221220bb1d83ee5ac25b848f5792c22f73093728abddb826df6c4a5c2a0b3c0b46f7d864736f6c63430008170033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000a1d5b81d0024809faa278ab72fe3d2fb467dd28b00000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd340000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104c25760003560e01c80637f472e5411610286578063cdc82e801161016b578063e1ba95d2116100e3578063f2caeb1e11610097578063facefb641161007c578063facefb6414610af4578063fbfa77cf14610b07578063fff6cae914610b2757600080fd5b8063f2caeb1e14610ace578063f77e34d114610ae157600080fd5b8063ebe2b12b116100c8578063ebe2b12b14610ab3578063f288baf614610abc578063f2a8d34914610ac557600080fd5b8063e1ba95d214610a98578063e7f3058214610aa057600080fd5b8063d5e1a9c61161013a578063d9f96e8d1161011f578063d9f96e8d14610a48578063de1a655114610a7d578063e01f62bf14610a9057600080fd5b8063d5e1a9c614610a22578063d7400d5614610a3557600080fd5b8063cdc82e80146109ea578063d2010fb4146109f3578063d2fbdc0d146109fc578063d42fc9b414610a0f57600080fd5b8063aa1d4fce116101fe578063bdb123e3116101cd578063c3543826116101b2578063c354382614610998578063c8f33c91146109ab578063ca6df29d146109b457600080fd5b8063bdb123e31461097d578063c00007b01461098557600080fd5b8063aa1d4fce14610945578063af48e59a1461094e578063b85efd0614610961578063b94c4dcb1461097457600080fd5b80638da5cb5b116102555780639637927f1161023a5780639637927f14610912578063a0f234761461091f578063a321ff971461093257600080fd5b80638da5cb5b146108df57806391cf600a146108ff57600080fd5b80637f472e54146108765780638980f11f1461088957806389b5f00b1461089c5780638bad86a7146108b157600080fd5b806341a16f3f116103ac5780636e27cef911610324578063774d4ae7116102f35780637970833e116102d85780637970833e1461081357806379ba50971461084e5780637d6ef08e1461085657600080fd5b8063774d4ae7146107ed5780637910d17b1461080057600080fd5b80636e27cef9146107a957806370641a36146107b257806372f702f3146107ba578063741d3c18146107da57600080fd5b806354fd4d501161037b57806364f2c0601161036057806364f2c0601461076157806369339245146107695780636c430dbb1461078957600080fd5b806354fd4d50146107515780635bfd92581461075957600080fd5b806341a16f3f146106d357806341edbdf0146107095780634fd2b5361461071e57806353a47bb71461073157600080fd5b80631face8561161043f5780632c0c2a0a1161040e57806336f89af2116103f357806336f89af214610680578063386a9525146106b6578063387edc86146106c057600080fd5b80632c0c2a0a1461065a5780632df079f11461066d57600080fd5b80631face856146105ce578063231b68dc146105e15780632352aac11461060457806328408bab1461062457600080fd5b806312edb24c1161049657806317b18c891161047b57806317b18c89146105935780631c1f78eb146105a65780631e090f01146105ae57600080fd5b806312edb24c146105695780631627540c1461057e57600080fd5b80628cc262146104c75780630238b936146104f057806307546172146105115780630d7bac4f14610556575b600080fd5b6104da6104d53660046156db565b610b2f565b6040516104e791906156f8565b60405180910390f35b6105036104fe36600461574a565b610ca4565b6040519081526020016104e7565b6004546105319073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104e7565b61050361056436600461578c565b610da5565b610571610dd1565b6040516104e791906157a5565b61059161058c3660046156db565b610e40565b005b6105036105a13660046157f3565b610f60565b6104da610fea565b6105c16105bc3660046156db565b611081565b6040516104e79190615815565b6105036105dc3660046156db565b611135565b6105f46105ef366004615883565b61117b565b60405190151581526020016104e7565b6029546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6105316106323660046156db565b60236020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6105036106683660046156db565b611261565b61059161067b3660046158bc565b61154d565b61050361068e3660046156db565b73ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205490565b61050362093a8081565b6105916106ce3660046156db565b6116c6565b6105316106e13660046156db565b60116020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b610711611825565b6040516104e7919061593c565b61050361072c3660046156db565b6118b3565b6001546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6107116118d4565b6105036118e1565b601f54610503565b6105036107773660046156db565b60176020526000908152604090205481565b6105036107973660046156db565b601b6020526000908152604090205481565b610503600a5481565b6104da611b1c565b6003546105319073ffffffffffffffffffffffffffffffffffffffff1681565b6105916107e83660046156db565b611c71565b6105036107fb36600461598d565b611dd4565b6104da61080e3660046159b9565b611fe0565b61082661082136600461598d565b61205c565b604080519586526020860194909452928401919091526060830152608082015260a0016104e7565b6105916120aa565b6105036108643660046156db565b60226020526000908152604090205481565b6105036108843660046156db565b6121f5565b61059161089736600461598d565b61220c565b6024546105f490640100000000900460ff1681565b6108c46108bf3660046156db565b61239d565b604080519384526020840192909252908201526060016104e7565b6000546105319073ffffffffffffffffffffffffffffffffffffffff1681565b61059161090d3660046156db565b6125c9565b6024546105f49060ff1681565b61050361092d3660046156db565b6126bc565b6105916109403660046156db565b612786565b610503600b5481565b61059161095c366004615883565b6128af565b61059161096f3660046157f3565b6129a1565b61050360095481565b610503612c38565b6104da6109933660046156db565b612d7d565b6105316109a63660046156db565b612e05565b61050360075481565b6105036109c23660046156db565b73ffffffffffffffffffffffffffffffffffffffff1660009081526027602052604090205490565b61050360085481565b61050360055481565b610591610a0a3660046157f3565b612e68565b610503610a1d3660046156db565b6132b5565b610591610a303660046159e7565b6132f0565b610591610a433660046156db565b6134df565b610503610a563660046156db565b73ffffffffffffffffffffffffffffffffffffffff16600090815260208052604090205490565b610591610a8b366004615883565b6136fa565b601e54610503565b6105916137e1565b610591610aae3660046156db565b6138b2565b61050360065481565b610503600c5481565b610503600d5481565b610503610adc36600461578c565b613a13565b610591610aef366004615a2f565b613b2a565b610591610b02366004615aca565b613cf6565b602a546105319073ffffffffffffffffffffffffffffffffffffffff1681565b610591613ea5565b60606000610b3b611b1c565b60125490915067ffffffffffffffff811115610b5957610b59615a4c565b604051908082528060200260200182016040528015610b82578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff841660009081526021602052604090205490925015610c9e5760005b601254811015610c9c5773ffffffffffffffffffffffffffffffffffffffff84166000818152601a60209081526040808320858452825280832054938352601982528083208584529091529020548351670de0b6b3a76400009190859085908110610c2157610c21615b48565b6020026020010151610c339190615ba6565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260216020526040902054610c639190615bb9565b610c6d9190615bd0565b610c779190615c0b565b838281518110610c8957610c89615b48565b6020908102919091010152600101610bb4565b505b50919050565b60006002805403610d16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602454610100900460ff1615610d8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610d0d565b610d9833848685613f4a565b6001600255949350505050565b600854600954600091610dcb91610dbc8286615bb9565b610dc69190615bd0565b614104565b92915050565b60606012805480602002602001604051908101604052809291908181526020018280548015610e3657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e0b575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ee7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610d0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610fcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055610fde338085854261411c565b60016002559392505050565b60155460609067ffffffffffffffff81111561100857611008615a4c565b604051908082528060200260200182016040528015611031578160200160208202803683370190505b50905060005b60155481101561107d5762093a8061104e82613a13565b6110589190615bb9565b82828151811061106a5761106a615b48565b6020908102919091010152600101611037565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561112a57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906110c6565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260226020526040812054600554670de0b6b3a76400009161117191615bb9565b610dcb9190615bd0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526016602052604081205460ff166111b057506000610dcb565b73ffffffffffffffffffffffffffffffffffffffff831615806111e7575073ffffffffffffffffffffffffffffffffffffffff8216155b156111f457506000610dcb565b60005473ffffffffffffffffffffffffffffffffffffffff9081169084160361121f57506001610dcb565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526011602052604090205481851691160361125857506001610dcb565b50600092915050565b6000808061126e84612e05565b905073ffffffffffffffffffffffffffffffffffffffff811615611333576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e9190615c1e565b6113d5565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156113b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d59190615c1e565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615c1e565b61146f9190615bb9565b600b54600c5461147f9086615bb9565b6114899190615bb9565b6114939190615bd0565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156114c2576114bd846121f5565b6114cb565b6114cb876118b3565b9050801561151d576000816114e8670de0b6b3a764000088615bb9565b6114f29190615bd0565b9050670de0b6b3a7640000600c548261150b9190615bb9565b6115159190615bd0565b925050611522565b600091505b508082116115305780611532565b815b9450600c5485111561154457600c5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806115865750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6115ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff16620100008415150217905580801561168b5750602454640100000000900460ff16155b156116c057602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b6002805403611731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055602454640100000000900460ff16156117aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b60245462010000900460ff161561181d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d0d565b506001600255565b602b805461183290615c37565b80601f016020809104026020016040519081016040528092919081815260200182805461185e90615c37565b80156118ab5780601f10611880576101008083540402835291602001916118ab565b820191906000526020600020905b81548152906001019060200180831161188e57829003601f168201915b505050505081565b6000670de0b6b3a7640000600d546118ca846132b5565b6111719190615bb9565b6025805461183290615c37565b600080602960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338fff2d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190615c1e565b602a546040517ff94d46680000000000000000000000000000000000000000000000000000000081526004810183905291925060009173ffffffffffffffffffffffffffffffffffffffff9091169063f94d466890602401600060405180830381865afa1580156119ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a309190810190615d17565b50915050600081600181518110611a4957611a49615b48565b602002602001015190506000611a5d612c38565b611a679083615bb9565b611a76906402540be400615bb9565b9050602960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663876f303b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b099190615c1e565b611b139082615bd0565b94505050505090565b6060601e5460001480611b2f5750601f54155b15611b89576018805480602002602001604051908101604052809291908181526020018280548015610e3657602002820191906000526020600020905b815481526020019060010190808311611b6c575050505050905090565b60125467ffffffffffffffff811115611ba457611ba4615a4c565b604051908082528060200260200182016040528015611bcd578160200160208202803683370190505b50905060005b60185481101561107d57601f54611be982613a13565b600754611bf46144d9565b611bfe9190615ba6565b611c089190615bb9565b611c1a90670de0b6b3a7640000615bb9565b611c249190615bd0565b60188281548110611c3757611c37615b48565b9060005260206000200154611c4c9190615c0b565b828281518110611c5e57611c5e615b48565b6020908102919091010152600101611bd3565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611caa5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff8116611d8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610d0d565b602880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602760205260408120805482919084908110611e0e57611e0e615b48565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff89168552601b9092528320549193501115611e8c57506020810151611eb4565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601b60205260409020545b42826060015111611f7457606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601b60205260409020541015611f6b576000818360600151611f029190615ba6565b90506000836060015142611f169190615ba6565b90506000611f28610564600285615bd0565b90506000611f368382615bb9565b611f408584615bb9565b611f4a9190615c0b565b9050611f568385615c0b565b611f609082615bd0565b965050505050611fc4565b60009250611fc4565b600080828460600151611f879190615ba6565b90506000428560600151611f9b9190615ba6565b90506002611fa98284615c0b565b611fb39190615bd0565b92505050611fc081610da5565b9350505b8160800151831115611fd857816080015192505b505092915050565b6060600280540361204d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055610fde3384846144ec565b6027602052816000526040600020818154811061207857600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314612151576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610d0d565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600d546118ca84611135565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806122395750612239338261117b565b61229f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526016602052604090205460ff168080156122fb575073ffffffffffffffffffffffffffffffffffffffff8481166000908152601160205260409020541633145b80612326575080158015612326575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15612336576116c0843385614825565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610d0d565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526021602052604081205490806123ce84611261565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260208052604081205491935090158015612427575073ffffffffffffffffffffffffffffffffffffffff8516600090815260216020526040902054155b80612457575073ffffffffffffffffffffffffffffffffffffffff85166000908152600e60205260409020548310155b156124635750816124a3565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600e60205260409020546002906124969085615c0b565b6124a09190615bd0565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff86166000908152602760205260409020548110156125c05773ffffffffffffffffffffffffffffffffffffffff8616600090815260276020526040812080548390811061250e5761250e615b48565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006125678884611dd4565b60408301519091506000670de0b6b3a76400006125848785615c0b565b61258e9084615bb9565b6125989190615bd0565b6125a29083615c0b565b90506125ae8188615c0b565b965050600190930192506124aa915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806126025750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff166000908152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600554600d546126ce9190615bb9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277c9190615c1e565b6118ca9190615bb9565b60005473ffffffffffffffffffffffffffffffffffffffff163314806127bf5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612825576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b600480546040517fdd289d6000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481169382019390935291169063dd289d6090602401600060405180830381600087803b15801561289457600080fd5b505af11580156128a8573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806128e85750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61294e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b6004805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617909155602a8054929093169116179055565b6002805403612a0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b600280556024546301000000900460ff1615612a84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b602454640100000000900460ff1615612af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b612b05333360016144ec565b50600080612b13338561498e565b915091506000838360400151612b299190615c0b565b9050600354612b509073ffffffffffffffffffffffffffffffffffffffff16333087614b5c565b6040805160a081018252868152602085810151818301528183018490526060808701519083015260808087015190830152336000908152602790915291909120805484908110612ba257612ba2615b48565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612bf133856001614cfa565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd19190615dff565b94509450509350935060008312158015612cea57508115155b8015612d0e57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b612d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610d0d565b50909392505050565b60606002805403612dea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b60028055612dfa338360016144ec565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f602052604081205460ff1615612e37575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602360205260409020541690565b919050565b6002805403612ed3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d0d565b600280556024546301000000900460ff1615612f4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b602454640100000000900460ff1615612fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b612fcc333360016144ec565b50600080612fda338561498e565b91509150428311613047576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610d0d565b60004283606001511161305b57600061306b565b42836060015161306b9190615ba6565b905060006130794286615ba6565b90508181116130e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610d0d565b600a54811015613150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d0d565b6009548111156131bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d0d565b6040518060a00160405280878152602001428152602001856040015181526020018681526020016131ec83610da5565b905233600090815260276020526040902080548590811061320f5761320f615b48565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505061325f3360006001614e69565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600554670de0b6b3a76400009161117191615bb9565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061331d575061331d338261117b565b613383576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601760205260409020546015805486929081106133be576133be615b48565b9060005260206000200181905550826013601760008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548154811061341f5761341f615b48565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94851617905591871681526017909152604090205460148054849290811061349057613490615b48565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f602052604090205460ff1661356e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260106020908152604080832033845290915290205460ff16613608576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610d0d565b3360009081526023602052604090205473ffffffffffffffffffffffffffffffffffffffff16801561367c57336000908152602080805260408083205473ffffffffffffffffffffffffffffffffffffffff8516845260229092528220805491929091613676908490615ba6565b90915550505b33600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915582805281842054908452602290925282208054919290916136f1908490615c0b565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff163314806137275750613727338261117b565b61378d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610d0d565b5073ffffffffffffffffffffffffffffffffffffffff918216600090815260116020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061381a5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600f602052604090205460ff1661392b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610d0d565b33600081815260106020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603613a105773ffffffffffffffffffffffffffffffffffffffff8116600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690558180528083205433845260229092528220805491929091613a0a908490615ba6565b90915550505b50565b60008060138381548110613a2957613a29615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015613b0457670de0b6b3a7640000601c8481548110613a6f57613a6f615b48565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae99190615c1e565b613af39190615bb9565b613afd9190615bd0565b9150610c9e565b60158381548110613b1757613b17615b48565b9060005260206000200154915050919050565b60005b601354811015613cf257600060138281548110613b4c57613b4c615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015613ce9578280613b9e5750601d8281548110613b9057613b90615b48565b906000526020600020015442115b15613ce9576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c399190615c1e565b601c8381548110613c4c57613c4c615b48565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc99190615c1e565b601d8381548110613cdc57613cdc615b48565b6000918252602090912001555b50600101613b2d565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480613d2f5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613d95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610d0d565b8051670de0b6b3a76400001115613e08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610d0d565b608081015160011115613e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610d0d565b80516008556020810151600c556040810151600d556060810151600b55608081015160095560a00151600a55565b602454640100000000900460ff1615613f1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b613f246000613b2a565b613f2c6118e1565b6005556006544210613f4257613f40614fe8565b565b613f40615564565b602454600090640100000000900460ff16613f6d57613f6b858560016144ec565b505b600080613f7a878661498e565b91509150816060015142101580613f98575060245460ff1615156001145b613ffe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610d0d565b604082015180156140f95760035461402d9073ffffffffffffffffffffffffffffffffffffffff168883614825565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260276020526040902080548390811061406457614064615b48565b60009182526020822060059091020181815560018101829055600281018290556003810182905560040181905561409e9089908390614cfa565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b60008183106141135781614115565b825b9392505050565b600085600161412d82826000614e69565b602454640100000000900460ff16156141a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b6024546301000000900460ff1615614216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610d0d565b600a54851015614282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610d0d565b6009548511156142ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610d0d565b6003546143139073ffffffffffffffffffffffffffffffffffffffff16883089614b5c565b600061431e86610da5565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152602080805260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526027835283902060a0850184528185529184018a90529183018b9052909250906060810161440f8a8a615c0b565b8152602090810185905282546001818101855560009485529382902083516005909202019081559082015181840155604082015160028201556060820151600382015560809091015160049091015561446b908b908a90614cfa565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006144e742600654614104565b905090565b60608360016144fd82826000614e69565b602454640100000000900460ff1615614572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610d0d565b60245462010000900460ff16156145e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610d0d565b73ffffffffffffffffffffffffffffffffffffffff86166000908152601b6020526040902042905560125467ffffffffffffffff81111561462857614628615a4c565b604051908082528060200260200182016040528015614651578160200160208202803683370190505b50925060005b60125481101561481b5773ffffffffffffffffffffffffffffffffffffffff87166000908152601a6020908152604080832084845290915290205484518590839081106146a6576146a6615b48565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff88166000908152601a8252604080822084835290925290812081905584518590839081106146fa576146fa615b48565b60200260200101511115614813576147696012828154811061471e5761471e615b48565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168786848151811061475c5761475c615b48565b6020026020010151614825565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff8583815181106147b3576147b3615b48565b6020026020010151601284815481106147ce576147ce615b48565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101614657565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916148bc9190615e4f565b6000604051808303816000865af19150503d80600081146148f9576040519150601f19603f3d011682016040523d82523d6000602084013e6148fe565b606091505b50915091508180156149285750805115806149285750808060200190518101906149289190615e6b565b6128a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610d0d565b6149c36040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b60008215614ae05760005b73ffffffffffffffffffffffffffffffffffffffff8516600090815260276020526040902054811015614ade5773ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020805482908110614a3257614a32615b48565b9060005260206000209060050201600001548403614ad65773ffffffffffffffffffffffffffffffffffffffff85166000908152602760205260409020805482908110614a8157614a81615b48565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150614ade565b6001016149ce565b505b8215801590614aef5750815183145b614b55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610d0d565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691614bfb9190615e4f565b6000604051808303816000865af19150503d8060008114614c38576040519150601f19603f3d011682016040523d82523d6000602084013e614c3d565b606091505b5091509150818015614c67575080511580614c67575080806020019051810190614c679190615e6b565b614cf2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610d0d565b505050505050565b6000614d0584612e05565b90508115614db95782601e6000828254614d1f9190615c0b565b909155505073ffffffffffffffffffffffffffffffffffffffff8416600090815260208052604081208054859290614d58908490615c0b565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614db45773ffffffffffffffffffffffffffffffffffffffff811660009081526022602052604081208054859290614dae908490615c0b565b90915550505b614e60565b82601e6000828254614dcb9190615ba6565b909155505073ffffffffffffffffffffffffffffffffffffffff8416600090815260208052604081208054859290614e04908490615ba6565b909155505073ffffffffffffffffffffffffffffffffffffffff811615614e605773ffffffffffffffffffffffffffffffffffffffff811660009081526022602052604081208054859290614e5a908490615ba6565b90915550505b6116c084600060015b602454640100000000900460ff16614e89578115614e8957614e89613ea5565b8015614ebf57614e9883611261565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600e60205260409020555b73ffffffffffffffffffffffffffffffffffffffff831615612398576000806000614ee98661239d565b6024549295509093509150640100000000900460ff16614f0c57614f0c866155cd565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600e60205260409020829055828110614f90576000614f478483615ba6565b905080601f54614f579190615c0b565b601f55614f648185615c0b565b73ffffffffffffffffffffffffffffffffffffffff881660009081526021602052604090205550614cf2565b6000614f9c8285615ba6565b905080601f54614fac9190615ba6565b601f55614fb98185615ba6565b73ffffffffffffffffffffffffffffffffffffffff881660009081526021602052604090205550505050505050565b614ff0615564565b60005b6014548110156150d75760006014828154811061501257615012615b48565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156150ce576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af11580156150a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150cb9190615e88565b50505b50600101614ff3565b50600062093a80600654426150ec9190615ba6565b6150f69190615bd0565b905060005b6012548110156152cf576012818154811061511857615118615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561518f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151b39190615c1e565b6151be836001615c0b565b62093a806151cb84613a13565b6151d59190615bb9565b6151df9190615bb9565b1115601282815481106151f4576151f4615b48565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166044820152605801604051602081830303815290604052906152c6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0d919061593c565b506001016150fb565b5062093a806152df826001615c0b565b6152e99190615bb9565b6006546152f69190615c0b565b60065560158054600190811061530e5761530e615b48565b9060005260206000200154600014615560576000601260018154811061533657615336615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156153ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153d19190615c1e565b600480546003546040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216938101939093529293509190911690636a627842906024016020604051808303816000875af115801561544d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906154719190615c1e565b506000601260018154811061548857615488615b48565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156154ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906155239190615c1e565b905062093a806155338383615ba6565b61553d9190615bd0565b601560018154811061555157615551615b48565b60009182526020909120015550505b613a105b600061556e611b1c565b905060005b6018548110156155be5781818151811061558f5761558f615b48565b6020026020010151601882815481106155aa576155aa615b48565b600091825260209091200155600101615573565b506155c76144d9565b60075550565b73ffffffffffffffffffffffffffffffffffffffff811615613a105760006155f482610b2f565b905060005b81518110156156585781818151811061561457615614615b48565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601a8352604080822085835290935291909120556001016155f9565b5060005b8151811015612398576018818154811061567857615678615b48565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260198252604080842085855290925291205560010161565c565b73ffffffffffffffffffffffffffffffffffffffff81168114613a1057600080fd5b6000602082840312156156ed57600080fd5b8135614115816156b9565b6020808252825182820181905260009190848201906040850190845b8181101561573057835183529284019291840191600101615714565b50909695505050505050565b8015158114613a1057600080fd5b60008060006060848603121561575f57600080fd5b833592506020840135615771816156b9565b915060408401356157818161573c565b809150509250925092565b60006020828403121561579e57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561573057835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016157c1565b6000806040838503121561580657600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b828110156158765781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101615832565b5091979650505050505050565b6000806040838503121561589657600080fd5b82356158a1816156b9565b915060208301356158b1816156b9565b809150509250929050565b600080600080608085870312156158d257600080fd5b84356158dd8161573c565b935060208501356158ed8161573c565b925060408501356158fd8161573c565b9150606085013561590d8161573c565b939692955090935050565b60005b8381101561593357818101518382015260200161591b565b50506000910152565b602081526000825180602084015261595b816040850160208701615918565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156159a057600080fd5b82356159ab816156b9565b946020939093013593505050565b600080604083850312156159cc57600080fd5b82356159d7816156b9565b915060208301356158b18161573c565b600080600080608085870312156159fd57600080fd5b8435615a08816156b9565b9350602085013592506040850135615a1f816156b9565b9150606085013561590d816156b9565b600060208284031215615a4157600080fd5b81356141158161573c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715615ac257615ac2615a4c565b604052919050565b600060c08284031215615adc57600080fd5b82601f830112615aeb57600080fd5b60405160c0810181811067ffffffffffffffff82111715615b0e57615b0e615a4c565b6040528060c0840185811115615b2357600080fd5b845b81811015615b3d578035835260209283019201615b25565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610dcb57610dcb615b77565b8082028115828204841417610dcb57610dcb615b77565b600082615c06577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610dcb57610dcb615b77565b600060208284031215615c3057600080fd5b5051919050565b600181811c90821680615c4b57607f821691505b602082108103610c9e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600067ffffffffffffffff821115615c9e57615c9e615a4c565b5060051b60200190565b600082601f830112615cb957600080fd5b81516020615cce615cc983615c84565b615a7b565b8083825260208201915060208460051b870101935086841115615cf057600080fd5b602086015b84811015615d0c5780518352918301918301615cf5565b509695505050505050565b600080600060608486031215615d2c57600080fd5b835167ffffffffffffffff80821115615d4457600080fd5b818601915086601f830112615d5857600080fd5b81516020615d68615cc983615c84565b82815260059290921b8401810191818101908a841115615d8757600080fd5b948201945b83861015615dae578551615d9f816156b9565b82529482019490820190615d8c565b91890151919750909350505080821115615dc757600080fd5b50615dd486828701615ca8565b925050604084015190509250925092565b805169ffffffffffffffffffff81168114612e6357600080fd5b600080600080600060a08688031215615e1757600080fd5b615e2086615de5565b9450602086015193506040860151925060608601519150615e4360808701615de5565b90509295509295909350565b60008251615e61818460208701615918565b9190910192915050565b600060208284031215615e7d57600080fd5b81516141158161573c565b60008060408385031215615e9b57600080fd5b50508051602090910151909290915056fea2646970667358221220bb1d83ee5ac25b848f5792c22f73093728abddb826df6c4a5c2a0b3c0b46f7d864736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000a1d5b81d0024809faa278ab72fe3d2fb467dd28b00000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd340000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0xba100000625a3754423978a60c9317c58a424e3D
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27,0x0000000000000000000000000000000000000000
Arg [3] : _rewardRates (uint256[]): 115740740740,100000000000
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34,0x0000000000000000000000000000000000000000
Arg [6] : _stakingToken (address): 0xA1D5B81d0024809FAA278Ab72fe3D2FB467Dd28b
-----Encoded View---------------
22 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [6] : 000000000000000000000000a1d5b81d0024809faa278ab72fe3d2fb467dd28b
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [11] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [14] : 0000000000000000000000000000000000000000000000000000001af2af8c84
Arg [15] : 000000000000000000000000000000000000000000000000000000174876e800
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [20] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
106367:4502:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42485:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93977:316;;;;;;:::i;:::-;;:::i;:::-;;;1786:25:1;;;1774:2;1759:18;93977:316:0;1640:177:1;32672:91:0;;;;;;;;;;;;2022:42:1;2010:55;;;1992:74;;1980:2;1965:18;32672:91:0;1822:250:1;45383:222:0;;;;;;:::i;:::-;;:::i;40487:109::-;;;:::i;:::-;;;;;;;:::i;25490:141::-;;;;;;:::i;:::-;;:::i;:::-;;91808:190;;;;;;:::i;:::-;;:::i;43193:339::-;;;:::i;85840:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;46215:179::-;;;;;;:::i;:::-;;:::i;39899:459::-;;;;;;:::i;:::-;;:::i;:::-;;;4957:14:1;;4950:22;4932:41;;4920:2;4905:18;39899:459:0;4792:187:1;106601:35:0;;;;;;;;;36345:60;;;;;;:::i;:::-;;;;;;;;;;;;;;;;48742:1752;;;;;;:::i;:::-;;:::i;65418:572::-;;;;;;:::i;:::-;;:::i;44594:127::-;;;;;;:::i;:::-;44687:26;;44660:7;44687:26;;;:17;:26;;;;;;;44594:127;35181:48;;35223:6;35181:48;;55403:309;;;;;;:::i;:::-;;:::i;34770:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;106774:46;;;:::i;:::-;;;;;;;:::i;47377:181::-;;;;;;:::i;:::-;;:::i;25258:29::-;;;;;;;;;37178:31;;;:::i;109411:1455::-;;;:::i;44202:111::-;44283:22;;44202:111;;35091:55;;;;;;:::i;:::-;;;;;;;;;;;;;;35573:54;;;;;;:::i;:::-;;;;;;;;;;;;;;34022:32;;;;;;41492:681;;;:::i;32635:30::-;;;;;;;;;109158:245;;;;;;:::i;:::-;;:::i;81031:2692::-;;;;;;:::i;:::-;;:::i;56660:206::-;;;;;;:::i;:::-;;:::i;75543:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;8059:25:1;;;8115:2;8100:18;;8093:34;;;;8143:18;;;8136:34;;;;8201:2;8186:18;;8179:34;8244:3;8229:19;;8222:35;8046:3;8031:19;75543:53:0;7800:463:1;25639:271:0;;;:::i;36140:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;47754:199;;;;;;:::i;:::-;;:::i;66786:818::-;;;;;;:::i;:::-;;:::i;37118:34::-;;;;;;;;;;;;83784:1961;;;;;;:::i;:::-;;:::i;:::-;;;;8470:25:1;;;8526:2;8511:18;;8504:34;;;;8554:18;;;8547:34;8458:2;8443:18;83784:1961:0;8268:319:1;25231:20:0;;;;;;;;;66390:161;;;;;;:::i;:::-;;:::i;36467:26::-;;;;;;;;;46671:224;;;;;;:::i;:::-;;:::i;108148:135::-;;;;;;:::i;:::-;;:::i;34094:55::-;;;;;;107925:172;;;;;;:::i;:::-;;:::i;88681:1290::-;;;;;;:::i;:::-;;:::i;33867:62::-;;;;;;108803:347;;;:::i;56198:172::-;;;;;;:::i;:::-;;:::i;48106:444::-;;;;;;:::i;:::-;;:::i;33713:29::-;;;;;;86049:133;;;;;;:::i;:::-;86146:21;;86119:7;86146:21;;;:12;:21;;;;;:28;;86049:133;33793:50;;;;;;33386:30;;;;;;90025:1648;;;;;;:::i;:::-;;:::i;45840:166::-;;;;;;:::i;:::-;;:::i;69579:483::-;;;;;;:::i;:::-;;:::i;51514:800::-;;;;;;:::i;:::-;;:::i;43960:128::-;;;;;;:::i;:::-;44054:26;;44027:7;44054:26;;;:17;:26;;;;;;;43960:128;70382:207;;;;;;:::i;:::-;;:::i;43695:113::-;43777:23;;43695:113;;66154:97;;;:::i;50748:610::-;;;;;;:::i;:::-;;:::i;33606:27::-;;;;;;34232:51;;;;;;34308:59;;;;;;40970:452;;;;;;:::i;:::-;;:::i;63479:761::-;;;;;;:::i;:::-;;:::i;68067:958::-;;;;;;:::i;:::-;;:::i;106643:27::-;;;;;;;;;64339:482;;;:::i;42485:529::-;42539:27;42579;42609:17;:15;:17::i;:::-;42664:12;:19;42579:47;;-1:-1:-1;42650:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42650:34:0;-1:-1:-1;42701:26:0;;;42730:1;42701:26;;;:17;:26;;;;;;42637:47;;-1:-1:-1;42701:30:0;42697:310;;42752:9;42747:249;42771:12;:19;42767:23;;42747:249;;;42961:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;42880:32;;;:23;:32;;;;;:35;;;;;;;;;42864:13;;42920:4;;42880:35;42864:10;;42978:1;;42864:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;42834:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;42833:91;;;;:::i;:::-;42832:148;;;;:::i;:::-;42816:10;42827:1;42816:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;42792:3;;42747:249;;;;42697:310;42568:446;42485:529;;;:::o;93977:316::-;94108:7;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;;;;;;;;;29507:1;30246:18;;94136:17:::1;::::0;::::1;::::0;::::1;;;:26;94128:57;;;::::0;::::1;::::0;;13077:2:1;94128:57:0::1;::::0;::::1;13059:21:1::0;13116:2;13096:18;;;13089:30;13155:20;13135:18;;;13128:48;13193:18;;94128:57:0::1;12875:342:1::0;94128:57:0::1;94203:82;94219:10;94231:19;94252:6;94260:24;94203:15;:82::i;:::-;29463:1:::0;30425:7;:22;94196:89;93977:316;-1:-1:-1;;;;93977:316:0:o;45383:222::-;45492:19;;45557:28;;45442:7;;45469:127;;45527:26;45492:19;45527:4;:26;:::i;:::-;45526:59;;;;:::i;:::-;45469:8;:127::i;:::-;45462:134;45383:222;-1:-1:-1;;45383:222:0:o;40487:109::-;40540:16;40576:12;40569:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40487:109;:::o;25490:141::-;25970:5;;;;25956:10;:19;25948:79;;;;;;;13424:2:1;25948:79:0;;;13406:21:1;13463:2;13443:18;;;13436:30;13502:34;13482:18;;;13475:62;13573:17;13553:18;;;13546:45;13608:19;;25948:79:0;13222:411:1;25948:79:0;25562:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;25601:22:::1;::::0;1992:74:1;;;25601:22:0::1;::::0;1980:2:1;1965:18;25601:22:0::1;;;;;;;25490:141:::0;:::o;91808:190::-;91893:7;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;91920:70:::1;91933:10;::::0;91957:9;91968:4;91974:15:::1;91920:12;:70::i;:::-;29463:1:::0;30425:7;:22;91913:77;91808:190;-1:-1:-1;;;91808:190:0:o;43193:339::-;43343:17;:24;43248:41;;43329:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43329:39:0;;43302:66;;43386:9;43381:144;43405:17;:24;43401:28;;43381:144;;;35223:6;43481:14;43493:1;43481:11;:14::i;:::-;:32;;;;:::i;:::-;43451:24;43476:1;43451:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;43431:3;;43381:144;;;;43193:339;:::o;85840:133::-;85944:21;;;;;;;:12;:21;;;;;;;;85937:28;;;;;;;;;;;;;;;;;85904:20;;85937:28;;85944:21;;85937:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85840:133;;;:::o;46215:179::-;46330:32;;;46284:7;46330:32;;;:17;:32;;;;;;46312:15;;33514:4;;46312:50;;;:::i;:::-;46311:75;;;;:::i;39899:459::-;40016:32;;;39995:4;40016:32;;;:13;:32;;;;;;;;40011:297;;-1:-1:-1;40057:5:0;40050:12;;40011:297;40082:25;;;;;:60;;-1:-1:-1;40111:31:0;;;;40082:60;40078:230;;;-1:-1:-1;40151:5:0;40144:12;;40078:230;40191:5;;;;;;40176:20;;;;40172:136;;-1:-1:-1;40205:4:0;40198:11;;40172:136;40247:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;40243:65;;-1:-1:-1;40304:4:0;40297:11;;40243:65;-1:-1:-1;40344:5:0;39899:459;;;;:::o;48742:1752::-;48805:24;;;48966:20;48978:7;48966:11;:20::i;:::-;48946:40;-1:-1:-1;49017:23:0;;;;49016:81;;49071:26;;;;;2022:42:1;2010:55;;49071:26:0;;;1992:74:1;33121:42:0;;49071:15;;1965:18:1;;49071:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49016:81;;;49044:24;;;;;2022:42:1;2010:55;;49044:24:0;;;1992:74:1;33121:42:0;;49044:15;;1965:18:1;;49044:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48997:100;;49203:19;33514:4;33121:42;49327:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;49268:24;;49245:20;;49226:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;49225:145;;;;:::i;:::-;49203:167;-1:-1:-1;49479:19:0;;49694:23;;;;49693:94;;49752:35;49777:9;49752:24;:35::i;:::-;49693:94;;;49721:28;49741:7;49721:19;:28::i;:::-;49664:123;-1:-1:-1;49808:30:0;;49804:323;;49859:27;49933:26;49890:39;33514:4;49890:16;:39;:::i;:::-;49889:70;;;;:::i;:::-;49859:100;;33514:4;50033:20;;50011:19;:42;;;;:::i;:::-;50010:67;;;;:::i;:::-;49996:81;;49839:254;49804:323;;;50126:1;50112:15;;49804:323;49509:699;50295:11;50281;:25;:53;;50323:11;50281:53;;;50309:11;50281:53;50261:74;;50425:20;;50406:16;:39;50402:84;;;50466:20;;50447:39;;50402:84;48831:1663;;;;48742:1752;;;:::o;65418:572::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;65620:13:::1;:30:::0;;65661:38;;65620:30;;::::1;;;65661:38:::0;;;65620:30:::1;65661:38:::0;::::1;;;;65710:50:::0;::::1;::::0;;::::1;;;;::::0;;65901:23;:50;::::1;;;-1:-1:-1::0;65929:22:0::1;::::0;;;::::1;;;65928:23;65901:50;65898:84;;;65953:22;:29:::0;;;::::1;::::0;::::1;::::0;;65898:84:::1;65418:572:::0;;;;:::o;55403:309::-;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;55501:22:::1;::::0;;;::::1;;;55500:23;55492:60;;;::::0;::::1;::::0;;14379:2:1;55492:60:0::1;::::0;::::1;14361:21:1::0;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;55492:60:0::1;14177:348:1::0;55492:60:0::1;55571:23;::::0;;;::::1;;;:32;55563:70;;;::::0;::::1;::::0;;14732:2:1;55563:70:0::1;::::0;::::1;14714:21:1::0;14771:2;14751:18;;;14744:30;14810:27;14790:18;;;14783:55;14855:18;;55563:70:0::1;14530:349:1::0;55563:70:0::1;-1:-1:-1::0;29463:1:0;30425:7;:22;55403:309::o;106774:46::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;47377:181::-;47444:7;33514:4;47498:28;;47472:23;47487:7;47472:14;:23::i;:::-;:54;;;;:::i;37178:31::-;;;;;;;:::i;109411:1455::-;109467:25;109730:15;109748:6;;;;;;;;;;;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109877:5;;:28;;;;;;;;1786:25:1;;;109730:36:0;;-1:-1:-1;109846:25:0;;109877:5;;;;;:19;;1759:18:1;;109877:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109842:63;;;;109920:22;109945:8;109954:1;109945:11;;;;;;;;:::i;:::-;;;;;;;109920:36;;109971:28;110037:21;:19;:21::i;:::-;110012:47;;:14;:47;:::i;:::-;110002:58;;110003:4;110002:58;:::i;:::-;109971:89;;110181:6;;;;;;;;;;;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110156:49;;110157:20;110156:49;:::i;:::-;110136:69;;109683:534;;;;109411:1455;:::o;41492:681::-;41540:41;41598:23;;41625:1;41598:28;:59;;;-1:-1:-1;41630:22:0;;:27;41598:59;41594:572;;;41681:21;41674:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41492:681;:::o;41594:572::-;41785:12;:19;41771:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41771:34:0;;41744:61;;41825:9;41820:289;41844:21;:28;41840:32;;41820:289;;;42052:22;;42027:14;42039:1;42027:11;:14::i;:::-;42009;;41980:26;:24;:26::i;:::-;:43;;;;:::i;:::-;41979:62;;;;:::i;:::-;:69;;42044:4;41979:69;:::i;:::-;41978:96;;;;:::i;:::-;41928:21;41950:1;41928:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;41898:24;41923:1;41898:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;41874:3;;41820:289;;109158:245;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;109255:37:::1;::::0;::::1;109247:71;;;::::0;::::1;::::0;;17850:2:1;109247:71:0::1;::::0;::::1;17832:21:1::0;17889:2;17869:18;;;17862:30;17928:23;17908:18;;;17901:51;17969:18;;109247:71:0::1;17648:345:1::0;109247:71:0::1;109331:15;:64:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;109158:245::o;81031:2692::-;81222:21;;;81120:32;81222:21;;;:12;:21;;;;;:32;;81120;;81222:21;81244:9;;81222:32;;;;;;:::i;:::-;;;;;;;;;81191:63;;;;;;;;81222:32;;;;;;;81191:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81437:28;;;;;:19;:28;;;;;;81191:63;;-1:-1:-1;;81433:224:0;;;-1:-1:-1;81530:25:0;;;;81433:224;;;-1:-1:-1;81617:28:0;;;;;;;:19;:28;;;;;;81433:224;81746:15;81716:9;:26;;;:45;81712:1802;;81941:26;;;;81910:28;;;;;;;:19;:28;;;;;;:57;81906:1087;;;81987:26;82045:17;82016:9;:26;;;:46;;;;:::i;:::-;81987:75;;82081:25;82127:9;:26;;;82109:15;:44;;;;:::i;:::-;82081:72;-1:-1:-1;82233:33:0;82269:38;82284:22;82305:1;82284:18;:22;:::i;82269:38::-;82233:74;-1:-1:-1;82524:17:0;82596:21;82600:17;82524;82596:21;:::i;:::-;82545:46;82573:18;82545:25;:46;:::i;:::-;82544:74;;;;:::i;:::-;82524:94;-1:-1:-1;82677:38:0;82698:17;82677:18;:38;:::i;:::-;82664:52;;:9;:52;:::i;:::-;82637:79;;81968:764;;;;81712:1802;;81906:1087;82976:1;82949:28;;81712:1802;;;83138:21;83193:20;83245:17;83216:9;:26;;;:46;;;;:::i;:::-;83193:69;;83281:20;83333:15;83304:9;:26;;;:44;;;;:::i;:::-;83281:67;-1:-1:-1;83415:1:0;83384:27;83281:67;83384:12;:27;:::i;:::-;83383:33;;;;:::i;:::-;83367:49;;83174:258;;83473:29;83488:13;83473:14;:29::i;:::-;83446:56;;83058:456;81712:1802;83636:9;:25;;;83609:24;:52;83605:110;;;83690:9;:25;;;83663:52;;83605:110;81154:2569;;81031:2692;;;;:::o;56660:206::-;56762:16;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;56798:60:::1;56809:10;56821:19:::0;56842:15;56798:10:::1;:60::i;75543:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75543:53:0;;-1:-1:-1;75543:53:0;;;:::o;25639:271::-;25708:14;;;;25694:10;:28;25686:94;;;;;;;18200:2:1;25686:94:0;;;18182:21:1;18239:2;18219:18;;;18212:30;18278:34;18258:18;;;18251:62;18349:23;18329:18;;;18322:51;18390:19;;25686:94:0;17998:417:1;25686:94:0;25809:5;;;25816:14;25796:35;;;25809:5;;;;18655:34:1;;25816:14:0;;;;18720:2:1;18705:18;;18698:43;25796:35:0;;18567:18:1;25796:35:0;;;;;;;25850:14;;;;25842:22;;;;;;25850:14;;;25842:22;;;;25875:27;;;25639:271::o;47754:199::-;47832:7;33514:4;47893:28;;47860:30;47876:13;47860:15;:30::i;66786:818::-;37591:5;;66872:12;;37591:5;;37577:10;:19;;:74;;;37600:51;37618:10;37630:20;37600:17;:51::i;:::-;37569:107;;;;;;;18954:2:1;37569:107:0;;;18936:21:1;18993:2;18973:18;;;18966:30;19032:22;19012:18;;;19005:50;19072:18;;37569:107:0;18752:344:1;37569:107:0;66970:27:::1;::::0;::::1;66954:13;66970:27:::0;;;:13:::1;:27;::::0;;;;;::::1;;::::0;67224:54;::::1;;;-1:-1:-1::0;67236:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;67268:10;67236:42;67224:54;67223:113;;;;67302:8;67301:9;:34;;;;-1:-1:-1::0;67329:5:0::1;::::0;::::1;;67315:10;:19;67301:34;67201:396;;;67367:66;67395:12;67409:10;67421:11;67367:27;:66::i;67201:396::-;67549:36;::::0;::::1;::::0;;19303:2:1;67549:36:0::1;::::0;::::1;19285:21:1::0;19342:2;19322:18;;;19315:30;19381:28;19361:18;;;19354:56;19427:18;;67549:36:0::1;19101:350:1::0;37687:1:0::1;66786:818:::0;;;:::o;83784:1961::-;84087:26;;;83885:27;84087:26;;;:17;:26;;;;;;;83885:27;84274:24;84105:7;84274:15;:24::i;:::-;84374:26;;;84311:33;84374:26;;;:17;:26;;;;;;84251:47;;-1:-1:-1;84311:33:0;84374:31;:66;;;;-1:-1:-1;84409:26:0;;;;;;;:17;:26;;;;;;:31;84374:66;84373:143;;;-1:-1:-1;84484:31:0;;;;;;;:22;:31;;;;;;84460:55;;;84373:143;84355:638;;;-1:-1:-1;84757:20:0;84355:638;;;84945:31;;;;;;;:22;:31;;;;;;84980:1;;84922:54;;:20;:54;:::i;:::-;84921:60;;;;:::i;:::-;84893:88;;84355:638;85128:1;85106:23;;85145:9;85140:598;85164:21;;;;;;;:12;:21;;;;;:28;85160:32;;85140:598;;;85245:21;;;85214:28;85245:21;;;:12;:21;;;;;:24;;85267:1;;85245:24;;;;;;:::i;:::-;;;;;;;;;;;85214:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85341:32;85376:34;85399:7;85408:1;85376:22;:34::i;:::-;85492:19;;;;85341:69;;-1:-1:-1;85472:17:0;33514:4;85587:52;85614:25;85341:69;85587:52;:::i;:::-;85574:66;;:9;:66;:::i;:::-;85573:91;;;;:::i;:::-;85560:105;;:9;:105;:::i;:::-;85526:139;-1:-1:-1;85680:46:0;85526:139;85680:46;;:::i;:::-;;-1:-1:-1;;85194:3:0;;;;;-1:-1:-1;85140:598:0;;-1:-1:-1;;85140:598:0;;;84014:1731;83784:1961;;;;;:::o;66390:161::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;66511:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;66475:68;;::::1;66511:32;::::0;;::::1;66510:33;66475:68;::::0;;66390:161::o;46671:224::-;46737:7;46871:15;;46840:28;;:46;;;;:::i;:::-;46765:24;;;;;2022:42:1;2010:55;;46765:24:0;;;1992:74:1;33514:4:0;;;;33121:42;;46765:15;;1965:18:1;;46765:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;108148:135::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;108239:6:::1;::::0;;:36:::1;::::0;;;;:6:::1;2010:55:1::0;;;108239:36:0;;::::1;1992:74:1::0;;;;108239:6:0;::::1;::::0;:26:::1;::::0;1965:18:1;;108239:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;108148:135:::0;:::o;107925:172::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;108015:6:::1;:33:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;108059:5:::1;:30:::0;;;;;::::1;::::0;::::1;;::::0;;107925:172::o;88681:1290::-;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;88822:13:::1;::::0;;;::::1;;;88821:14;88813:41;;;::::0;::::1;::::0;;19658:2:1;88813:41:0::1;::::0;::::1;19640:21:1::0;19697:2;19677:18;;;19670:30;19736:16;19716:18;;;19709:44;19770:18;;88813:41:0::1;19456:338:1::0;88813:41:0::1;88922:22;::::0;;;::::1;;;88921:23;88913:60;;;::::0;::::1;::::0;;14379:2:1;88913:60:0::1;::::0;::::1;14361:21:1::0;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;88913:60:0::1;14177:348:1::0;88913:60:0::1;89037:40;89048:10;89060;89072:4;89037:10;:40::i;:::-;;89139:28;89169:21:::0;89194:29:::1;89204:10;89216:6;89194:9;:29::i;:::-;89138:85;;;;89273:15;89313:8;89291:9;:19;;;:30;;;;:::i;:::-;89273:48:::0;-1:-1:-1;89492:12:0::1;::::0;89452:91:::1;::::0;89492:12:::1;;89507:10;89527:4;89534:8:::0;89452:31:::1;:91::i;:::-;89627:186;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;89674:25:::0;;::::1;::::0;89627:186;;::::1;::::0;;;;;;;;89736:26;;::::1;::::0;89627:186;;;;;89777:25;;::::1;::::0;89627:186;;;;89598:10:::1;-1:-1:-1::0;89585:24:0;;;:12:::1;:24:::0;;;;;;;:39;;89610:13;;89585:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89857:42;89872:10;89884:8;89894:4;89857:14;:42::i;:::-;89917:46;::::0;;20318:25:1;;;20374:2;20359:18;;20352:34;;;89934:10:0::1;::::0;89917:46:::1;::::0;20291:18:1;89917:46:0::1;;;;;;;-1:-1:-1::0;;29463:1:0;30425:7;:22;-1:-1:-1;;;88681:1290:0:o;108803:347::-;108855:3;108898:14;108914:9;108927:17;108946:22;108972:15;;;;;;;;;;;:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108897:108;;;;;;;;;109033:1;109024:5;:10;;:27;;;;-1:-1:-1;109038:13:0;;;109024:27;:57;;;;;109074:7;109055:26;;:15;:26;;;;109024:57;109016:93;;;;;;;21261:2:1;109016:93:0;;;21243:21:1;21300:2;21280:18;;;21273:30;21339:25;21319:18;;;21312:53;21382:18;;109016:93:0;21059:347:1;109016:93:0;-1:-1:-1;109137:5:0;;108803:347;-1:-1:-1;;;108803:347:0:o;56198:172::-;56277:16;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;56313:49:::1;56324:10;56336:19:::0;56357:4:::1;56313:10;:49::i;:::-;29463:1:::0;30425:7;:22;56306:56;56198:172;-1:-1:-1;;56198:172:0:o;48106:444::-;48185:25;;;48162:7;48185:25;;;:19;:25;;;;;;;;48181:362;;;-1:-1:-1;48388:4:0;48106:444::o;48181:362::-;-1:-1:-1;48500:31:0;;;;;;;;:25;:31;;;;;;;;48106:444::o;48181:362::-;48106:444;;;:::o;90025:1648::-;29507:1;30113:7;;:19;30105:63;;;;;;;12717:2:1;30105:63:0;;;12699:21:1;12756:2;12736:18;;;12729:30;12795:33;12775:18;;;12768:61;12846:18;;30105:63:0;12515:355:1;30105:63:0;29507:1;30246:18;;90167:13:::1;::::0;;;::::1;;;90166:14;90158:41;;;::::0;::::1;::::0;;19658:2:1;90158:41:0::1;::::0;::::1;19640:21:1::0;19697:2;19677:18;;;19670:30;19736:16;19716:18;;;19709:44;19770:18;;90158:41:0::1;19456:338:1::0;90158:41:0::1;90267:22;::::0;;;::::1;;;90266:23;90258:60;;;::::0;::::1;::::0;;14379:2:1;90258:60:0::1;::::0;::::1;14361:21:1::0;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;90258:60:0::1;14177:348:1::0;90258:60:0::1;90382:40;90393:10;90405;90417:4;90382:10;:40::i;:::-;;90484:28;90514:21:::0;90539:29:::1;90549:10;90561:6;90539:9;:29::i;:::-;90483:85;;;;90623:15;90607:13;:31;90599:65;;;::::0;::::1;::::0;;21613:2:1;90599:65:0::1;::::0;::::1;21595:21:1::0;21652:2;21632:18;;;21625:30;21691:23;21671:18;;;21664:51;21732:18;;90599:65:0::1;21411:345:1::0;90599:65:0::1;90710:17;90760:15;90731:9;:26;;;:44;90730:97;;90826:1;90730:97;;;90808:15;90779:9;:26;;;:44;;;;:::i;:::-;90710:117:::0;-1:-1:-1;90838:16:0::1;90857:31;90873:15;90857:13:::0;:31:::1;:::i;:::-;90838:50;;90994:9;90983:8;:20;90975:57;;;::::0;::::1;::::0;;21963:2:1;90975:57:0::1;::::0;::::1;21945:21:1::0;22002:2;21982:18;;;21975:30;22041:26;22021:18;;;22014:54;22085:18;;90975:57:0::1;21761:348:1::0;90975:57:0::1;91063:13;;91051:8;:25;;91043:64;;;::::0;::::1;::::0;;22316:2:1;91043:64:0::1;::::0;::::1;22298:21:1::0;22355:2;22335:18;;;22328:30;22394:28;22374:18;;;22367:56;22440:18;;91043:64:0::1;22114:350:1::0;91043:64:0::1;91138:28;;91126:8;:40;;91118:80;;;::::0;::::1;::::0;;22671:2:1;91118:80:0::1;::::0;::::1;22653:21:1::0;22710:2;22690:18;;;22683:30;22749:29;22729:18;;;22722:57;22796:18;;91118:80:0::1;22469:351:1::0;91118:80:0::1;91282:174;;;;;;;;91308:6;91282:174;;;;91329:15;91282:174;;;;91359:9;:19;;;91282:174;;;;91393:13;91282:174;;;;91421:24;91436:8;91421:14;:24::i;:::-;91282:174:::0;;91253:10:::1;91240:24;::::0;;;:12:::1;:24;::::0;;;;:39;;91265:13;;91240:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91525:48;91549:10;91561:5;91568:4;91525:23;:48::i;:::-;91591:74;::::0;;23056:25:1;;;23112:2;23097:18;;23090:34;;;91634:15:0::1;23140:18:1::0;;;23133:34;23198:2;23183:18;;23176:34;;;91591:74:0;;91604:10:::1;::::0;91591:74:::1;::::0;;;;;23043:3:1;91591:74:0;;::::1;-1:-1:-1::0;;29463:1:0;30425:7;:22;-1:-1:-1;;;;90025:1648:0:o;45840:166::-;45948:26;;;45902:7;45948:26;;;:17;:26;;;;;;45930:15;;33514:4;;45930:44;;;:::i;69579:483::-;37591:5;;69745:20;;37591:5;;37577:10;:19;;:74;;;37600:51;37618:10;37630:20;37600:17;:51::i;:::-;37569:107;;;;;;;18954:2:1;37569:107:0;;;18936:21:1;18993:2;18973:18;;;18966:30;19032:22;19012:18;;;19005:50;19072:18;;37569:107:0;18752:344:1;37569:107:0;69796:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;69778:17:::1;:61:::0;;69842:9;;69796:42;69778:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;69925:25;69862:16;69879:20;:42;69900:20;69879:42;;;;;;;;;;;;;;;;69862:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;69980:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;69961:18:::1;:62:::0;;70026:28;;69980:42;69961:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;69579:483:::0;;;;;:::o;51514:800::-;51594:34;;;;;;;:19;:34;;;;;;;;51586:60;;;;;;;23423:2:1;51586:60:0;;;23405:21:1;23462:2;23442:18;;;23435:30;23501:15;23481:18;;;23474:43;23534:18;;51586:60:0;23221:337:1;51586:60:0;51665:36;;;;;;;:21;:36;;;;;;;;51702:10;51665:48;;;;;;;;;;51657:90;;;;;;;23765:2:1;51657:90:0;;;23747:21:1;23804:2;23784:18;;;23777:30;23843:31;23823:18;;;23816:59;23892:18;;51657:90:0;23563:353:1;51657:90:0;51893:10;51842:22;51867:37;;;:25;:37;;;;;;;;51919:28;;51915:182;;52074:10;52056:29;;;;:17;:29;;;;;;;;;52019:33;;;;:17;:33;;;;;:66;;52056:29;;52019:33;;:66;;52056:29;;52019:66;:::i;:::-;;;;-1:-1:-1;;51915:182:0;52165:10;52139:37;;;;:25;:37;;;;;;;;:53;;;;:37;:53;;;;;;;;52277:29;;;;;;;52241:32;;;:17;:32;;;;;:65;;52277:29;;52241:32;;:65;;52277:29;;52241:65;:::i;:::-;;;;-1:-1:-1;;;;51514:800:0:o;70382:207::-;37591:5;;70490:20;;37591:5;;37577:10;:19;;:74;;;37600:51;37618:10;37630:20;37600:17;:51::i;:::-;37569:107;;;;;;;18954:2:1;37569:107:0;;;18936:21:1;18993:2;18973:18;;;18966:30;19032:22;19012:18;;;19005:50;19072:18;;37569:107:0;18752:344:1;37569:107:0;-1:-1:-1;70523:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;70382:207::o;66154:97::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;66229:14:::1;::::0;;66211:32;;::::1;66229:14;::::0;;::::1;66228:15;66211:32;::::0;;66154:97::o;50748:610::-;50847:10;50827:31;;;;:19;:31;;;;;;;;50819:57;;;;;;;23423:2:1;50819:57:0;;;23405:21:1;23462:2;23442:18;;;23435:30;23501:15;23481:18;;;23474:43;23534:18;;50819:57:0;23221:337:1;50819:57:0;50962:10;50940:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;50939:50;50887:102;;;;;;;51092:25;:41;;;;;;;;:55;51088:263;;51163:41;;;51215:1;51163:41;;;:25;:41;;;;;;;;:54;;;;;;51306:33;;;;;;;51291:10;51273:29;;:17;:29;;;;;:66;;51306:33;;51273:29;;:66;;51306:33;;51273:66;:::i;:::-;;;;-1:-1:-1;;51088:263:0;50748:610;:::o;40970:452::-;41031:16;41060:32;41095:16;41112:9;41095:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;41137:38:0;;41133:282;;41318:4;41276:27;41304:9;41276:38;;;;;;;;:::i;:::-;;;;;;;;;41225:24;41204:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;41203:119;;;;:::i;:::-;41192:130;;41133:282;;;41375:17;41393:9;41375:28;;;;;;;;:::i;:::-;;;;;;;;;41364:39;;41049:373;40970:452;;;:::o;63479:761::-;63596:9;63591:642;63615:16;:23;63611:27;;63591:642;;;63660:32;63695:16;63712:1;63695:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;63733:38:0;;63729:493;;63796:12;:61;;;;63831:22;63854:1;63831:25;;;;;;;;:::i;:::-;;;;;;;;;63813:15;:43;63796:61;63792:415;;;63971:106;;;;;64054:4;63971:106;;;24095:74:1;64061:15:0;24185:18:1;;;24178:34;63971:74:0;;;;;;24068:18:1;;63971:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63938:27;63966:1;63938:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;64149:24;64128:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64100:22;64123:1;64100:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;63792:415;-1:-1:-1;63640:3:0;;63591:642;;;;63479:761;:::o;68067:958::-;37388:5;;;;37374:10;:19;;:79;;-1:-1:-1;37411:42:0;37397:10;:56;37374:79;37366:113;;;;;;;14029:2:1;37366:113:0;;;14011:21:1;14068:2;14048:18;;;14041:30;14107:23;14087:18;;;14080:51;14148:18;;37366:113:0;13827:345:1;37366:113:0;68476:13;;33514:4:::1;-1:-1:-1::0;68476:37:0::1;68468:69;;;::::0;::::1;::::0;;24425:2:1;68468:69:0::1;::::0;::::1;24407:21:1::0;24464:2;24444:18;;;24437:30;24503:21;24483:18;;;24476:49;24542:18;;68468:69:0::1;24223:343:1::0;68468:69:0::1;68685:13:::0;;::::1;::::0;68702:1:::1;-1:-1:-1::0;68685:18:0::1;68676:45;;;::::0;::::1;::::0;;25114:2:1;68676:45:0::1;::::0;::::1;25096:21:1::0;25153:2;25133:18;;;25126:30;25192:14;25172:18;;;25165:42;25224:18;;68676:45:0::1;24912:336:1::0;68676:45:0::1;68756:13:::0;;68734:19:::1;:35:::0;68756:13:::1;68803::::0;::::1;::::0;68780:20:::1;:36:::0;68858:13;;::::1;::::0;68827:28:::1;:44:::0;68909:13;;::::1;::::0;68882:24:::1;:40:::0;68964:13;;::::1;::::0;68933:28:::1;:44:::0;69004:13;::::1;::::0;68988::::1;:29:::0;68067:958::o;64339:482::-;64428:22;;;;;;;64427:23;64419:60;;;;;;;14379:2:1;64419:60:0;;;14361:21:1;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;64419:60:0;14177:348:1;64419:60:0;64541:25;64560:5;64541:18;:25::i;:::-;64636:16;:14;:16::i;:::-;64618:15;:34;64688:12;;64669:15;:31;64665:149;;64717:14;:12;:14::i;:::-;64339:482::o;64665:149::-;64773:29;:27;:29::i;94804:1558::-;95266:22;;94990:7;;95266:22;;;;;95262:194;;95391:53;95402:14;95418:19;95439:4;95391:10;:53::i;:::-;;95262:194;95509:28;95539:21;95564:33;95574:14;95590:6;95564:9;:33::i;:::-;95508:89;;;;95635:9;:26;;;95616:15;:45;;:71;;;-1:-1:-1;95665:14:0;;;;:22;;:14;:22;95616:71;95608:106;;;;;;;25455:2:1;95608:106:0;;;25437:21:1;25494:2;25474:18;;;25467:30;25533:24;25513:18;;;25506:52;25575:18;;95608:106:0;25253:346:1;95608:106:0;95745:19;;;;95781:13;;95777:549;;95961:12;;95925:82;;95961:12;;95976:19;95997:9;95925:27;:82::i;:::-;96079:28;;;;;;;:12;:28;;;;;:43;;96108:13;;96079:43;;;;;;:::i;:::-;;;;;;;;;;;;;96072:50;;;;;;;;;;;;;;;;;;;;;;;;;;96174:48;;96189:14;;96205:9;;96174:14;:48::i;:::-;96244:70;;;25806:25:1;;;25862:2;25847:18;;25840:34;;;96244:70:0;25910:55:1;;;25890:18;;;25883:83;96244:70:0;;;;;;;;;;;25794:2:1;96244:70:0;;;95777:549;96345:9;94804:1558;-1:-1:-1;;;;;;;94804:1558:0:o;17920:106::-;17978:7;18009:1;18005;:5;:13;;18017:1;18005:13;;;18013:1;18005:13;17998:20;17920:106;-1:-1:-1;;;17920:106:0:o;92194:1421::-;92440:7;92409:14;92425:4;37782:49;37806:7;37815:8;37825:5;37782:23;:49::i;:::-;92469:22:::1;::::0;;;::::1;;;92468:23;92460:60;;;::::0;::::1;::::0;;14379:2:1;92460:60:0::1;::::0;::::1;14361:21:1::0;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;92460:60:0::1;14177:348:1::0;92460:60:0::1;92540:13;::::0;;;::::1;;;92539:14;92531:41;;;::::0;::::1;::::0;;19658:2:1;92531:41:0::1;::::0;::::1;19640:21:1::0;19697:2;19677:18;;;19670:30;19736:16;19716:18;;;19709:44;19770:18;;92531:41:0::1;19456:338:1::0;92531:41:0::1;92599:13;;92591:4;:21;;92583:60;;;::::0;::::1;::::0;;22316:2:1;92583:60:0::1;::::0;::::1;22298:21:1::0;22355:2;22335:18;;;22328:30;22394:28;22374:18;;;22367:56;22440:18;;92583:60:0::1;22114:350:1::0;92583:60:0::1;92670:28;;92662:4;:36;;92654:75;;;::::0;::::1;::::0;;22671:2:1;92654:75:0::1;::::0;::::1;22653:21:1::0;22710:2;22690:18;;;22683:30;22749:29;22729:18;;;22722:57;22796:18;;92654:75:0::1;22469:351:1::0;92654:75:0::1;92852:12;::::0;92812:96:::1;::::0;92852:12:::1;;92867:14:::0;92891:4:::1;92898:9:::0;92812:31:::1;:96::i;:::-;92968:23;92994:20;93009:4;92994:14;:20::i;:::-;93113:33;::::0;::::1;93025:14;93113:33:::0;;;:17:::1;:33:::0;;;;;;;;93052:95;;26223:66:1;26210:2;26206:15;;;26202:88;93052:95:0;;::::1;26190:101:1::0;;;;26307:12;;;26300:28;;;26344:12;;;26337:28;;;26381:12;;;26374:28;92968:46:0;;-1:-1:-1;93025:14:0;26418:13:1;;93052:95:0::1;::::0;;;;;::::1;::::0;;;;;;93042:106;;93052:95:::1;93042:106:::0;;::::1;::::0;93205:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;93239:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;93042:106;;-1:-1:-1;93205:28:0;93239:164;;;93340:22:::1;93358:4:::0;93286:15;93340:22:::1;:::i;:::-;93239:164:::0;;::::1;::::0;;::::1;::::0;;;93205:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;93205: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;93448:47:::1;::::0;93463:14;;93479:9;;93448:14:::1;:47::i;:::-;93513:68;::::0;;26673:25:1;;;26729:2;26714:18;;26707:34;;;26757:18;;;26750:34;;;93513:68:0::1;26820:55:1::0;;;26815:2;26800:18;;26793:83;93513:68:0;::::1;::::0;::::1;::::0;26660:3:1;26645:19;93513:68:0::1;;;;;;;93601:6:::0;92194:1421;-1:-1:-1;;;;;;;;;92194:1421:0:o;40648:133::-;40707:7;40734:39;40743:15;40760:12;;40734:8;:39::i;:::-;40727:46;;40648:133;:::o;56962:1313::-;57110:31;57085:8;57095:4;37782:49;37806:7;37815:8;37825:5;37782:23;:49::i;:::-;57209:22:::1;::::0;;;::::1;;;57208:23;57200:60;;;::::0;::::1;::::0;;14379:2:1;57200:60:0::1;::::0;::::1;14361:21:1::0;14418:2;14398:18;;;14391:30;14457:26;14437:18;;;14430:54;14501:18;;57200:60:0::1;14177:348:1::0;57200:60:0::1;57343:23;::::0;;;::::1;;;:32;57335:70;;;::::0;::::1;::::0;;14732:2:1;57335:70:0::1;::::0;::::1;14714:21:1::0;14771:2;14751:18;;;14744:30;14810:27;14790:18;;;14783:55;14855:18;;57335:70:0::1;14530:349:1::0;57335:70:0::1;57504:29;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;57536:15:::1;57504:47:::0;;57663:12:::1;:19:::0;57649:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;57649:34:0::1;;57632:51;;57701:9;57696:419;57720:12;:19:::0;57716:23;::::1;57696:419;;;57781:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;57761:17;;:14;;57799:1;;57761:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;57816:17:::1;::::0;::::1;57839:1;57816:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;57859:17;;:14;;57834:1;;57859:17;::::1;;;;;:::i;:::-;;;;;;;:21;57855:249;;;57901:84;57929:12;57942:1;57929:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;57946:19;57967:14;57982:1;57967:17;;;;;;;;:::i;:::-;;;;;;;57901:27;:84::i;:::-;58022:8;58011:77;;;58032:14;58047:1;58032:17;;;;;;;;:::i;:::-;;;;;;;58051:12;58064:1;58051:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;58011:77:::1;::::0;;27089:25:1;;;58051:15:0::1;::::0;;::::1;27191:18:1::0;;;27184:43;;;;27263:15;;27243:18;;;27236:43;27077:2;27062:18;58011:77:0::1;;;;;;;57855:249;57741:3;;57696:419;;;;56962:1313:::0;;;;;;;:::o;26773:361::-;26968:45;;;26957:10;24113:55:1;;;26968:45:0;;;24095:74:1;24185:18;;;;24178:34;;;26968:45:0;;;;;;;;;;24068:18:1;;;;26968:45:0;;;;;;;;;;;;;26957:57;;-1:-1:-1;;;;26957:10:0;;;;:57;;26968:45;26957:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26921:93;;;;27033:7;:57;;;;-1:-1:-1;27045:11:0;;:16;;:44;;;27076:4;27065:24;;;;;;;;;;;;:::i;:::-;27025:101;;;;;;;28034:2:1;27025:101:0;;;28016:21:1;28073:2;28053:18;;;28046:30;28112:33;28092:18;;;28085:61;28163:18;;27025:101:0;27832:355:1;88028:590:0;88110:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88110:31:0;88143:15;88175:11;;88171:347;;88208:9;88203:304;88227:28;;;;;;;:12;:28;;;;;:35;88223:39;;88203:304;;;88302:28;;;;;;;:12;:28;;;;;:31;;88331:1;;88302:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;88292:6;:48;88288:204;;88379:28;;;;;;;:12;:28;;;;;:31;;88408:1;;88379:31;;;;;;:::i;:::-;;;;;;;;;;;88364:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88443:1;88433:11;;88467:5;;88288:204;88264:3;;88203:304;;;;88171:347;88536:11;;;;;:44;;-1:-1:-1;88551:19:0;;:29;;88536:44;88528:72;;;;;;;28394:2:1;88528:72:0;;;28376:21:1;28433:2;28413:18;;;28406:30;28472:17;28452:18;;;28445:45;28507:18;;88528:72:0;28192:339:1;88528:72:0;88028:590;;;;;:::o;27142:402::-;27367:51;;;27356:10;28817:15:1;;;27367:51:0;;;28799:34:1;28869:15;;;28849:18;;;28842:43;28901:18;;;;28894:34;;;27367:51:0;;;;;;;;;;28711:18:1;;;;27367:51:0;;;;;;;;;;;;;27356:63;;-1:-1:-1;;;;27356:10:0;;;;:63;;27367:51;27356:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27320:99;;;;27438:7;:57;;;;-1:-1:-1;27450:11:0;;:16;;:44;;;27481:4;27470:24;;;;;;;;;;;;:::i;:::-;27430:106;;;;;;;29141:2:1;27430:106:0;;;29123:21:1;29180:2;29160:18;;;29153:30;29219:34;29199:18;;;29192:62;29290:6;29270:18;;;29263:34;29314:19;;27430:106:0;28939:400:1;27430:106:0;27230:314;;27142:402;;;;:::o;87143:877::-;87271:17;87291:27;87303:14;87291:11;:27::i;:::-;87271:47;;87335:6;87331:561;;;87426:3;87399:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;87444:33:0;;;;;;;:17;:33;;;;;:40;;87481:3;;87444:33;:40;;87481:3;;87444:40;:::i;:::-;;;;-1:-1:-1;;87538:23:0;;;;87534:64;;87563:28;;;;;;;:17;:28;;;;;:35;;87595:3;;87563:28;:35;;87595:3;;87563:35;:::i;:::-;;;;-1:-1:-1;;87534:64:0;87331:561;;;87708:3;87681:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;87726:33:0;;;;;;;:17;:33;;;;;:40;;87763:3;;87726:33;:40;;87763:3;;87726:40;:::i;:::-;;;;-1:-1:-1;;87820:23:0;;;;87816:64;;87845:28;;;;;;;:17;:28;;;;;:35;;87877:3;;87845:28;:35;;87877:3;;87845:35;:::i;:::-;;;;-1:-1:-1;;87816:64:0;87960:52;87984:14;88000:5;88007:4;52630:1962;52816:22;;;;;;;52811:214;;52964:8;52960:54;;;52992:6;:4;:6::i;:::-;53165:19;53161:109;;;53234:24;53250:7;53234:15;:24::i;:::-;53200:31;;;;;;;:22;:31;;;;;:58;53161:109;53294:21;;;;53290:1295;;53508:27;53554:28;53601:27;53646:30;53668:7;53646:21;:30::i;:::-;53743:22;;53486:190;;-1:-1:-1;53486:190:0;;-1:-1:-1;53486:190:0;-1:-1:-1;53743:22:0;;;;;53738:49;;53767:20;53779:7;53767:11;:20::i;:::-;53863:31;;;;;;;:22;:31;;;;;:54;;;54004:42;;;54000:572;;54067:19;54089:41;54111:19;54089;:41;:::i;:::-;54067:63;;54199:11;54174:22;;:36;;;;:::i;:::-;54149:22;:61;54258:33;54280:11;54258:19;:33;:::i;:::-;54229:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;54000:572:0;;;54332:19;54354:41;54376:19;54354;:41;:::i;:::-;54332:63;;54464:11;54439:22;;:36;;;;:::i;:::-;54414:22;:61;54523:33;54545:11;54523:19;:33;:::i;:::-;54494:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;53317:1268:0;;;52630:1962;;;:::o;58362:4514::-;58449:29;:27;:29::i;:::-;58568:9;58563:327;58587:18;:25;58583:29;;58563:327;;;58634:34;58671:18;58690:1;58671:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;58711:40:0;;58707:172;;58772:91;;;;;58857:4;58772:91;;;1992:74:1;58772:76:0;;;;;;1965:18:1;;58772:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;58707:172;-1:-1:-1;58614:3:0;;58563:327;;;;59250:27;35223:6;59306:12;;59288:15;:30;;;;:::i;:::-;59280:57;;;;:::i;:::-;59250:87;;59476:9;59471:284;59495:12;:19;59491:23;;59471:284;;;59617:12;59630:1;59617:15;;;;;;;;:::i;:::-;;;;;;;;;;;59610:48;;;;;59652:4;59610:48;;;1992:74:1;59617:15:0;;;;;59610:33;;1965:18:1;;59610:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59581:23;:19;59603:1;59581:23;:::i;:::-;35223:6;59545:14;59557:1;59545:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;59544:114;;59724:12;59737:1;59724:15;;;;;;;;:::i;:::-;;;;;;;;;;;;59667:73;;;29836:34:1;59667:73:0;;;29824:47:1;;;;29901:6;29887:12;;;29880:28;29946:2;29942:15;;;29924:12;;;29917:110;30043:12;;59667:73:0;;;;;;;;;;;;59536:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;59516:3:0;;59471:284;;;-1:-1:-1;35223:6:0;59967:23;:19;59989:1;59967:23;:::i;:::-;59966:43;;;;:::i;:::-;59950:12;;:60;;;;:::i;:::-;59935:12;:75;60342:17;:20;;60360:1;;60342:20;;;;;;:::i;:::-;;;;;;;;;60366:1;60342:25;60338:454;;60457:18;60485:12;60498:1;60485:15;;;;;;;;:::i;:::-;;;;;;;;;;;60478:48;;;;;60520:4;60478:48;;;1992:74:1;60485:15:0;;;;;60478:33;;1965:18:1;;60478:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60541:6;;;60561:12;;60541:34;;;;;:6;60561:12;;;60541:34;;;1992:74:1;;;;60457:69:0;;-1:-1:-1;60541:6:0;;;;;:11;;1965:18:1;;60541:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;60590:17;60617:12;60630:1;60617:15;;;;;;;;:::i;:::-;;;;;;;;;;;60610:48;;;;;60652:4;60610:48;;;1992:74:1;60617:15:0;;;;;60610:33;;1965:18:1;;60610:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60590:68;-1:-1:-1;35223:6:0;60739:22;60751:10;60590:68;60739:22;:::i;:::-;60738:42;;;;:::i;:::-;60715:17;60733:1;60715:20;;;;;;;;:::i;:::-;;;;;;;;;;:65;-1:-1:-1;;60338:454:0;62839:29;62884:435;62971:34;63008:17;:15;:17::i;:::-;62971:54;;63088:9;63083:133;63107:21;:28;63103:32;;63083:133;;;63184:17;63202:1;63184:20;;;;;;;;:::i;:::-;;;;;;;63157:21;63179:1;63157:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;63137:3;;63083:133;;;;63285:26;:24;:26::i;:::-;63268:14;:43;-1:-1:-1;62884:435:0:o;54600:585::-;54662:21;;;;54658:520;;54739:27;54769:15;54776:7;54769:6;:15::i;:::-;54739:45;;54847:9;54842:118;54866:10;:17;54862:1;:21;54842:118;;;54931:10;54942:1;54931:13;;;;;;;;:::i;:::-;;;;;;;;;;;;54909:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;54885:3;;54842:118;;;;55027:9;55022:145;55046:10;:17;55042:1;:21;55022:145;;;55127:21;55149:1;55127:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;55089:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;55065:3;;55022:145;;14:154:1;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:247;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;340:9;327:23;359:31;384:5;359:31;:::i;425:632::-;596:2;648:21;;;718:13;;621:18;;;740:22;;;567:4;;596:2;819:15;;;;793:2;778:18;;;567:4;862:169;876:6;873:1;870:13;862:169;;;937:13;;925:26;;1006:15;;;;971:12;;;;898:1;891:9;862:169;;;-1:-1:-1;1048:3:1;;425:632;-1:-1:-1;;;;;;425:632:1:o;1062:118::-;1148:5;1141:13;1134:21;1127:5;1124:32;1114:60;;1170:1;1167;1160:12;1185:450;1259:6;1267;1275;1328:2;1316:9;1307:7;1303:23;1299:32;1296:52;;;1344:1;1341;1334:12;1296:52;1380:9;1367:23;1357:33;;1440:2;1429:9;1425:18;1412:32;1453:31;1478:5;1453:31;:::i;:::-;1503:5;-1:-1:-1;1560:2:1;1545:18;;1532:32;1573:30;1532:32;1573:30;:::i;:::-;1622:7;1612:17;;;1185:450;;;;;:::o;2077:180::-;2136:6;2189:2;2177:9;2168:7;2164:23;2160:32;2157:52;;;2205:1;2202;2195:12;2157:52;-1:-1:-1;2228:23:1;;2077:180;-1:-1:-1;2077:180:1:o;2262:681::-;2433:2;2485:21;;;2555:13;;2458:18;;;2577:22;;;2404:4;;2433:2;2656:15;;;;2630:2;2615:18;;;2404:4;2699:218;2713:6;2710:1;2707:13;2699:218;;;2778:13;;2793:42;2774:62;2762:75;;2892:15;;;;2857:12;;;;2735:1;2728:9;2699:218;;2948:248;3016:6;3024;3077:2;3065:9;3056:7;3052:23;3048:32;3045:52;;;3093:1;3090;3083:12;3045:52;-1:-1:-1;;3116:23:1;;;3186:2;3171:18;;;3158:32;;-1:-1:-1;2948:248:1:o;3383:1011::-;3612:2;3664:21;;;3734:13;;3637:18;;;3756:22;;;3583:4;;3612:2;3797;;3815:18;;;;3856:15;;;3583:4;3899:469;3913:6;3910:1;3907:13;3899:469;;;3972:13;;4010:9;;3998:22;;4060:11;;;4054:18;4040:12;;;4033:40;4113:11;;;4107:18;4093:12;;;4086:40;4149:4;4193:11;;;4187:18;4173:12;;;4166:40;4229:4;4273:11;;;4267:18;4253:12;;;4246:40;4315:4;4306:14;;;;4343:15;;;;3935:1;3928:9;3899:469;;;-1:-1:-1;4385:3:1;;3383:1011;-1:-1:-1;;;;;;;3383:1011:1:o;4399:388::-;4467:6;4475;4528:2;4516:9;4507:7;4503:23;4499:32;4496:52;;;4544:1;4541;4534:12;4496:52;4583:9;4570:23;4602:31;4627:5;4602:31;:::i;:::-;4652:5;-1:-1:-1;4709:2:1;4694:18;;4681:32;4722:33;4681:32;4722:33;:::i;:::-;4774:7;4764:17;;;4399:388;;;;;:::o;5476:647::-;5550:6;5558;5566;5574;5627:3;5615:9;5606:7;5602:23;5598:33;5595:53;;;5644:1;5641;5634:12;5595:53;5683:9;5670:23;5702:28;5724:5;5702:28;:::i;:::-;5749:5;-1:-1:-1;5806:2:1;5791:18;;5778:32;5819:30;5778:32;5819:30;:::i;:::-;5868:7;-1:-1:-1;5927:2:1;5912:18;;5899:32;5940:30;5899:32;5940:30;:::i;:::-;5989:7;-1:-1:-1;6048:2:1;6033:18;;6020:32;6061:30;6020:32;6061:30;:::i;:::-;5476:647;;;;-1:-1:-1;5476:647:1;;-1:-1:-1;;5476:647:1:o;6128:250::-;6213:1;6223:113;6237:6;6234:1;6231:13;6223:113;;;6313:11;;;6307:18;6294:11;;;6287:39;6259:2;6252:10;6223:113;;;-1:-1:-1;;6370:1:1;6352:16;;6345:27;6128:250::o;6383:455::-;6532:2;6521:9;6514:21;6495:4;6564:6;6558:13;6607:6;6602:2;6591:9;6587:18;6580:34;6623:79;6695:6;6690:2;6679:9;6675:18;6670:2;6662:6;6658:15;6623:79;:::i;:::-;6754:2;6742:15;6759:66;6738:88;6723:104;;;;6829:2;6719:113;;6383:455;-1:-1:-1;;6383:455:1:o;7093:315::-;7161:6;7169;7222:2;7210:9;7201:7;7197:23;7193:32;7190:52;;;7238:1;7235;7228:12;7190:52;7277:9;7264:23;7296:31;7321:5;7296:31;:::i;:::-;7346:5;7398:2;7383:18;;;;7370:32;;-1:-1:-1;;;7093:315:1:o;7413:382::-;7478:6;7486;7539:2;7527:9;7518:7;7514:23;7510:32;7507:52;;;7555:1;7552;7545:12;7507:52;7594:9;7581:23;7613:31;7638:5;7613:31;:::i;:::-;7663:5;-1:-1:-1;7720:2:1;7705:18;;7692:32;7733:30;7692:32;7733:30;:::i;9025:598::-;9111:6;9119;9127;9135;9188:3;9176:9;9167:7;9163:23;9159:33;9156:53;;;9205:1;9202;9195:12;9156:53;9244:9;9231:23;9263:31;9288:5;9263:31;:::i;:::-;9313:5;-1:-1:-1;9365:2:1;9350:18;;9337:32;;-1:-1:-1;9421:2:1;9406:18;;9393:32;9434:33;9393:32;9434:33;:::i;:::-;9486:7;-1:-1:-1;9545:2:1;9530:18;;9517:32;9558:33;9517:32;9558:33;:::i;9628:241::-;9684:6;9737:2;9725:9;9716:7;9712:23;9708:32;9705:52;;;9753:1;9750;9743:12;9705:52;9792:9;9779:23;9811:28;9833:5;9811:28;:::i;9874:184::-;9926:77;9923:1;9916:88;10023:4;10020:1;10013:15;10047:4;10044:1;10037:15;10063:334;10134:2;10128:9;10190:2;10180:13;;10195:66;10176:86;10164:99;;10293:18;10278:34;;10314:22;;;10275:62;10272:88;;;10340:18;;:::i;:::-;10376:2;10369:22;10063:334;;-1:-1:-1;10063:334:1:o;10402:761::-;10484:6;10537:3;10525:9;10516:7;10512:23;10508:33;10505:53;;;10554:1;10551;10544:12;10505:53;10603:7;10596:4;10585:9;10581:20;10577:34;10567:62;;10625:1;10622;10615:12;10567:62;10658:2;10652:9;10700:3;10692:6;10688:16;10770:6;10758:10;10755:22;10734:18;10722:10;10719:34;10716:62;10713:88;;;10781:18;;:::i;:::-;10817:2;10810:22;10852:6;10896:3;10881:19;;10912;;;10909:39;;;10944:1;10941;10934:12;10909:39;10968:9;10986:146;11002:6;10997:3;10994:15;10986:146;;;11070:17;;11058:30;;11117:4;11108:14;;;;11019;10986:146;;;-1:-1:-1;11151:6:1;;10402:761;-1:-1:-1;;;;;10402:761:1:o;11422:184::-;11474:77;11471:1;11464:88;11571:4;11568:1;11561:15;11595:4;11592:1;11585:15;11611:184;11663:77;11660:1;11653:88;11760:4;11757:1;11750:15;11784:4;11781:1;11774:15;11800:128;11867:9;;;11888:11;;;11885:37;;;11902:18;;:::i;11933:168::-;12006:9;;;12037;;12054:15;;;12048:22;;12034:37;12024:71;;12075:18;;:::i;12106:274::-;12146:1;12172;12162:189;;12207:77;12204:1;12197:88;12308:4;12305:1;12298:15;12336:4;12333:1;12326:15;12162:189;-1:-1:-1;12365:9:1;;12106:274::o;12385:125::-;12450:9;;;12471:10;;;12468:36;;;12484:18;;:::i;13638:184::-;13708:6;13761:2;13749:9;13740:7;13736:23;13732:32;13729:52;;;13777:1;13774;13767:12;13729:52;-1:-1:-1;13800:16:1;;13638:184;-1:-1:-1;13638:184:1:o;14884:437::-;14963:1;14959:12;;;;15006;;;15027:61;;15081:4;15073:6;15069:17;15059:27;;15027:61;15134:2;15126:6;15123:14;15103:18;15100:38;15097:218;;15171:77;15168:1;15161:88;15272:4;15269:1;15262:15;15300:4;15297:1;15290:15;15515:183;15575:4;15608:18;15600:6;15597:30;15594:56;;;15630:18;;:::i;:::-;-1:-1:-1;15675:1:1;15671:14;15687:4;15667:25;;15515:183::o;15703:665::-;15768:5;15821:3;15814:4;15806:6;15802:17;15798:27;15788:55;;15839:1;15836;15829:12;15788:55;15868:6;15862:13;15894:4;15918:60;15934:43;15974:2;15934:43;:::i;:::-;15918:60;:::i;:::-;16000:3;16024:2;16019:3;16012:15;16052:4;16047:3;16043:14;16036:21;;16109:4;16103:2;16100:1;16096:10;16088:6;16084:23;16080:34;16066:48;;16137:3;16129:6;16126:15;16123:35;;;16154:1;16151;16144:12;16123:35;16190:4;16182:6;16178:17;16204:135;16220:6;16215:3;16212:15;16204:135;;;16286:10;;16274:23;;16317:12;;;;16237;;16204:135;;;-1:-1:-1;16357:5:1;15703:665;-1:-1:-1;;;;;;15703:665:1:o;16373:1270::-;16511:6;16519;16527;16580:2;16568:9;16559:7;16555:23;16551:32;16548:52;;;16596:1;16593;16586:12;16548:52;16629:9;16623:16;16658:18;16699:2;16691:6;16688:14;16685:34;;;16715:1;16712;16705:12;16685:34;16753:6;16742:9;16738:22;16728:32;;16798:7;16791:4;16787:2;16783:13;16779:27;16769:55;;16820:1;16817;16810:12;16769:55;16849:2;16843:9;16871:4;16895:60;16911:43;16951:2;16911:43;:::i;16895:60::-;16989:15;;;17071:1;17067:10;;;;17059:19;;17055:28;;;17020:12;;;;17095:19;;;17092:39;;;17127:1;17124;17117:12;17092:39;17151:11;;;;17171:210;17187:6;17182:3;17179:15;17171:210;;;17260:3;17254:10;17277:31;17302:5;17277:31;:::i;:::-;17321:18;;17204:12;;;;17359;;;;17171:210;;;17436:18;;;17430:25;17400:5;;-1:-1:-1;17430:25:1;;-1:-1:-1;;;17467:16:1;;;17464:36;;;17496:1;17493;17486:12;17464:36;;17519:74;17585:7;17574:8;17563:9;17559:24;17519:74;:::i;:::-;17509:84;;;17633:2;17622:9;17618:18;17612:25;17602:35;;16373:1270;;;;;:::o;20397:179::-;20475:13;;20528:22;20517:34;;20507:45;;20497:73;;20566:1;20563;20556:12;20581:473;20684:6;20692;20700;20708;20716;20769:3;20757:9;20748:7;20744:23;20740:33;20737:53;;;20786:1;20783;20776:12;20737:53;20809:39;20838:9;20809:39;:::i;:::-;20799:49;;20888:2;20877:9;20873:18;20867:25;20857:35;;20932:2;20921:9;20917:18;20911:25;20901:35;;20976:2;20965:9;20961:18;20955:25;20945:35;;20999:49;21043:3;21032:9;21028:19;20999:49;:::i;:::-;20989:59;;20581:473;;;;;;;;:::o;27290:287::-;27419:3;27457:6;27451:13;27473:66;27532:6;27527:3;27520:4;27512:6;27508:17;27473:66;:::i;:::-;27555:16;;;;;27290:287;-1:-1:-1;;27290:287:1:o;27582:245::-;27649:6;27702:2;27690:9;27681:7;27677:23;27673:32;27670:52;;;27718:1;27715;27708:12;27670:52;27750:9;27744:16;27769:28;27791:5;27769:28;:::i;29344:245::-;29423:6;29431;29484:2;29472:9;29463:7;29459:23;29455:32;29452:52;;;29500:1;29497;29490:12;29452:52;-1:-1:-1;;29523:16:1;;29579:2;29564:18;;;29558:25;29523:16;;29558:25;;-1:-1:-1;29344:245:1:o
Swarm Source
ipfs://bb1d83ee5ac25b848f5792c22f73093728abddb826df6c4a5c2a0b3c0b46f7d8
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.