Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 11 from a total of 11 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Sync | 20602466 | 551 days ago | IN | 0 ETH | 0.00148345 | ||||
| Get Reward2 | 19255975 | 739 days ago | IN | 0 ETH | 0.00943473 | ||||
| Stake Locked | 19255975 | 739 days ago | IN | 0 ETH | 0.02184822 | ||||
| Get Reward2 | 19242989 | 741 days ago | IN | 0 ETH | 0.00772241 | ||||
| Withdraw Locked | 19242989 | 741 days ago | IN | 0 ETH | 0.01704515 | ||||
| Stake Locked | 19242985 | 741 days ago | IN | 0 ETH | 0.02727915 | ||||
| Withdraw Locked | 19115157 | 759 days ago | IN | 0 ETH | 0.00816347 | ||||
| Stake Locked | 19115154 | 759 days ago | IN | 0 ETH | 0.00932992 | ||||
| Sync | 19107100 | 760 days ago | IN | 0 ETH | 0.00172818 | ||||
| Get Reward | 19107099 | 760 days ago | IN | 0 ETH | 0.005822 | ||||
| Stake Locked | 19107081 | 760 days ago | IN | 0 ETH | 0.00744111 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
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-28
*/
// 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/IAuraDeposit.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IAuraDeposit {
function allowance ( address owner, address spender ) external view returns ( uint256 );
function approve ( address spender, uint256 amount ) external returns ( bool );
function balanceOf ( address account ) external view returns ( uint256 );
function burn ( address _from, uint256 _amount ) external;
function decimals ( ) external view returns ( uint8 );
function decreaseAllowance ( address spender, uint256 subtractedValue ) external returns ( bool );
function increaseAllowance ( address spender, uint256 addedValue ) external returns ( bool );
function mint ( address _to, uint256 _amount ) external;
function name ( ) external view returns ( string memory );
function operator ( ) external view returns ( address );
function symbol ( ) external view returns ( string memory );
function totalSupply ( ) external view returns ( uint256 );
function transfer ( address recipient, uint256 amount ) external returns ( bool );
function transferFrom ( address sender, address recipient, uint256 amount ) external returns ( bool );
}
// File contracts/Misc_AMOs/balancer/IAuraDepositVault.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
interface IAuraDepositVault {
function addExtraReward ( address _reward ) external returns ( bool );
function allowance ( address owner, address spender ) external view returns ( uint256 );
function approve ( address spender, uint256 amount ) external returns ( bool );
function asset ( ) external view returns ( address );
function balanceOf ( address account ) external view returns ( uint256 );
function clearExtraRewards ( ) external;
function convertToAssets ( uint256 shares ) external view returns ( uint256 );
function convertToShares ( uint256 assets ) external view returns ( uint256 );
function currentRewards ( ) external view returns ( uint256 );
function decimals ( ) external view returns ( uint8 );
function deposit ( uint256 assets, address receiver ) external returns ( uint256 );
function duration ( ) external view returns ( uint256 );
function earned ( address account ) external view returns ( uint256 );
function extraRewards ( uint256 ) external view returns ( address );
function extraRewardsLength ( ) external view returns ( uint256 );
function getReward ( ) external returns ( bool );
function getReward ( address _account, bool _claimExtras ) external returns ( bool );
function historicalRewards ( ) external view returns ( uint256 );
function lastTimeRewardApplicable ( ) external view returns ( uint256 );
function lastUpdateTime ( ) external view returns ( uint256 );
function maxDeposit ( address ) external view returns ( uint256 );
function maxMint ( address owner ) external view returns ( uint256 );
function maxRedeem ( address owner ) external view returns ( uint256 );
function maxWithdraw ( address owner ) external view returns ( uint256 );
function mint ( uint256 shares, address receiver ) external returns ( uint256 );
function name ( ) external view returns ( string memory );
function newRewardRatio ( ) external view returns ( uint256 );
function operator ( ) external view returns ( address );
function periodFinish ( ) external view returns ( uint256 );
function pid ( ) external view returns ( uint256 );
function previewDeposit ( uint256 assets ) external view returns ( uint256 );
function previewMint ( uint256 shares ) external view returns ( uint256 );
function previewRedeem ( uint256 shares ) external view returns ( uint256 );
function previewWithdraw ( uint256 assets ) external view returns ( uint256 shares );
function processIdleRewards ( ) external;
function queueNewRewards ( uint256 _rewards ) external returns ( bool );
function queuedRewards ( ) external view returns ( uint256 );
function redeem ( uint256 shares, address receiver, address owner ) external returns ( uint256 );
function rewardManager ( ) external view returns ( address );
function rewardPerToken ( ) external view returns ( uint256 );
function rewardPerTokenStored ( ) external view returns ( uint256 );
function rewardRate ( ) external view returns ( uint256 );
function rewardToken ( ) external view returns ( address );
function rewards ( address ) external view returns ( uint256 );
function stake ( uint256 _amount ) external returns ( bool );
function stakeAll ( ) external returns ( bool );
function stakeFor ( address _for, uint256 _amount ) external returns ( bool );
function stakingToken ( ) external view returns ( address );
function symbol ( ) external view returns ( string memory );
function totalAssets ( ) external view returns ( uint256 );
function totalSupply ( ) external view returns ( uint256 );
function transfer ( address, uint256 ) external returns ( bool );
function transferFrom ( address, address, uint256 ) external returns ( bool );
function userRewardPerTokenPaid ( address ) external view returns ( uint256 );
function withdraw ( uint256 amount, bool claim ) external returns ( bool );
function withdraw ( uint256 assets, address receiver, address owner ) external returns ( uint256 );
function withdrawAll ( bool claim ) external;
function withdrawAllAndUnwrap ( bool claim ) external;
function withdrawAndUnwrap ( uint256 amount, bool claim ) external returns ( bool );
}
// File contracts/Staking/Owned.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
// https://docs.synthetix.io/contracts/Owned
contract Owned {
address public owner;
address public nominatedOwner;
constructor (address _owner) public {
require(_owner != address(0), "Owner address cannot be 0");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner {
require(msg.sender == owner, "Only the contract owner may perform this action");
_;
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}
// File contracts/Uniswap/TransferHelper.sol
// Original license: SPDX_License_Identifier: MIT
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
// File contracts/Utils/ReentrancyGuard.sol
// Original license: SPDX_License_Identifier: MIT
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
// File contracts/Staking/FraxUnifiedFarmTemplate.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ====================== FraxUnifiedFarmTemplate =====================
// ====================================================================
// Farming contract that accounts for veFXS
// Overrideable for UniV3, ERC20s, etc
// New for V2
// - Multiple reward tokens possible
// - Can add to existing locked stakes
// - Contract is aware of proxied veFXS
// - veFXS multiplier formula changed
// Apes together strong
// Frax Finance: https://github.com/FraxFinance
// Primary Author(s)
// Travis Moore: https://github.com/FortisFortuna
// Reviewer(s) / Contributor(s)
// Jason Huan: https://github.com/jasonhuan
// Sam Kazemian: https://github.com/samkazemian
// Dennis: github.com/denett
// Originally inspired by Synthetix.io, but heavily modified by the Frax team
// (Locked, veFXS, and UniV3 portions are new)
// https://raw.githubusercontent.com/Synthetixio/synthetix/develop/contracts/StakingRewards.sol
// Extra rewards
// Balancer
// ====================
// 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
IAuraDeposit public stakingToken;
IAuraDepositVault public aura_deposit_vault = IAuraDepositVault(0xE557658e3D13d074961265756dC2eFB6c903A763);
// Bunni
// IBunniGauge public stakingToken;
// IBunniLens public lens = IBunniLens(0xb73F303472C4fD4FF3B9f59ce0F9b13E47fbfD19);
// IBunniMinter public minter = IBunniMinter(0xF087521Ffca0Fa8A43F5C445773aB37C5f574DA0);
/* ========== STATE VARIABLES ========== */
// Instances
IveFXS private constant veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0);
// Frax related
address internal constant frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e;
/// @notice fraxPerLPToken is a public view function, although doesn't show the stored value
uint256 public fraxPerLPStored;
// Constant for various precisions
uint256 internal constant MULTIPLIER_PRECISION = 1e18;
// Time tracking
/// @notice Ending timestamp for the current period
uint256 public periodFinish;
/// @notice Timestamp of the last update - when this period started
uint256 public lastUpdateTime;
// Lock time and multiplier settings
uint256 public lock_max_multiplier = uint256(2e18); // E18. 1x = e18
uint256 public lock_time_for_max_multiplier = 1 * 1095 * 86400; // 3 years
// uint256 public lock_time_for_max_multiplier = 2 * 86400; // 2 days
uint256 public lock_time_min = 1; // 1 seconds. If 0, calcCurrLockMultiplier could div by 0
// veFXS related
uint256 public vefxs_boost_scale_factor = uint256(4e18); // E18. 4x = 4e18; 100 / scale_factor = % vefxs supply needed for max boost
uint256 public vefxs_max_multiplier = uint256(2e18); // E18. 1x = 1e18
uint256 public vefxs_per_frax_for_max_boost = uint256(4e18); // E18. 2e18 means 2 veFXS must be held by the staker per 1 FRAX
mapping(address => uint256) internal _vefxsMultiplierStored;
mapping(address => bool) internal valid_vefxs_proxies;
mapping(address => mapping(address => bool)) internal proxy_allowed_stakers;
// Reward addresses, gauge addresses, reward rates, and reward managers
/// @notice token addr -> manager addr
mapping(address => address) public rewardManagers;
address[] internal rewardTokens;
address[] internal gaugeControllers;
address[] internal rewardDistributors;
uint256[] internal rewardRatesManual;
mapping(address => bool) internal isRewardToken;
/// @notice token addr -> token index
mapping(address => uint256) public rewardTokenAddrToIdx;
// Reward period
uint256 public constant rewardsDuration = 604800; // 7 * 86400 (7 days)
// Reward tracking
uint256[] private rewardsPerTokenStored;
mapping(address => mapping(uint256 => uint256)) private userRewardsPerTokenPaid; // staker addr -> token id -> paid amount
mapping(address => mapping(uint256 => uint256)) private rewards; // staker addr -> token id -> reward amount
mapping(address => uint256) public lastRewardClaimTime; // staker addr -> timestamp
// Gauge tracking
uint256[] private last_gauge_relative_weights;
uint256[] private last_gauge_time_totals;
// Balance tracking
uint256 internal _total_liquidity_locked;
uint256 internal _total_combined_weight;
mapping(address => uint256) internal _locked_liquidity;
mapping(address => uint256) internal _combined_weights;
/// @notice Keeps track of LP balances proxy-wide. Needed to make sure the proxy boost is kept in line
mapping(address => uint256) public proxy_lp_balances;
/// @notice Stakers set which proxy(s) they want to use
/// @dev Keep public so users can see on the frontend if they have a proxy
mapping(address => address) public staker_designated_proxies;
// Admin booleans for emergencies and overrides
bool public stakesUnlocked; // Release locked stakes in case of emergency
bool internal withdrawalsPaused; // For emergencies
bool internal rewardsCollectionPaused; // For emergencies
bool internal stakingPaused; // For emergencies
// For emergencies if a token is overemitted or something else. Only callable once.
// Bypasses certain logic, which will cause reward calculations to be off
// But the goal is for the users to recover LP, and they couldn't claim the erroneous rewards anyways.
// Reward reimbursement claims would be handled with pre-issue earned() snapshots and a claim contract, or similar.
bool public withdrawalOnlyShutdown;
// Version
string public version = "1.0.6";
/* ========== STRUCTS ========== */
// In children...
/* ========== MODIFIERS ========== */
modifier onlyByOwnGov() {
require(msg.sender == owner || msg.sender == 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA, "Not owner or timelock");
_;
}
modifier onlyTknMgrs(address reward_token_address) {
require(msg.sender == owner || isTokenManagerFor(msg.sender, reward_token_address), "Not owner or tkn mgr");
_;
}
modifier updateRewardAndBalanceMdf(address account, bool sync_too) {
_updateRewardAndBalance(account, sync_too, false);
_;
}
/* ========== CONSTRUCTOR ========== */
constructor (
address _owner,
address[] memory _rewardTokens,
address[] memory _rewardManagers,
uint256[] memory _rewardRatesManual,
address[] memory _gaugeControllers,
address[] memory _rewardDistributors
) Owned(_owner) {
// Address arrays
rewardTokens = _rewardTokens;
gaugeControllers = _gaugeControllers;
rewardDistributors = _rewardDistributors;
rewardRatesManual = _rewardRatesManual;
for (uint256 i = 0; i < _rewardTokens.length; i++){
// For fast token address -> token ID lookups later
rewardTokenAddrToIdx[_rewardTokens[i]] = i;
// Add to the mapping
isRewardToken[_rewardTokens[i]] = true;
// Initialize the stored rewards
rewardsPerTokenStored.push(0);
// Initialize the reward managers
rewardManagers[_rewardTokens[i]] = _rewardManagers[i];
// Push in empty relative weights to initialize the array
last_gauge_relative_weights.push(0);
// Push in empty time totals to initialize the array
last_gauge_time_totals.push(0);
}
// Other booleans
stakesUnlocked = false;
// Initialization
lastUpdateTime = block.timestamp;
// Sync the first period finish here with the gauge's
// periodFinish = IFraxGaugeController(gaugeControllers[0]).time_total();
periodFinish = IFraxGaugeController(0x3669C421b77340B2979d1A00a792CC2ee0FcE737).time_total();
}
/* ============= VIEWS ============= */
// ------ REWARD RELATED ------
/// @notice Checks if the caller is a manager for the reward token
/// @param caller_addr The address of the caller
/// @param reward_token_addr The address of the reward token
/// @return bool True if the caller is a manager for the reward token
function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool){
if (!isRewardToken[reward_token_addr]) return false;
else if (caller_addr == address(0) || reward_token_addr == address(0)) return false;
else if (caller_addr == owner) return true; // Contract owner
else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager
return false;
}
/// @notice Gets all the reward tokens this contract handles
/// @return rewardTokens_ The reward tokens array
function getAllRewardTokens() external view returns (address[] memory) {
return rewardTokens;
}
// Last time the reward was applicable
function lastTimeRewardApplicable() internal view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
/// @notice The amount of reward tokens being paid out per second this period
/// @param token_idx The index of the reward token
/// @return rwd_rate The reward rate
function rewardRates(uint256 token_idx) public view returns (uint256 rwd_rate) {
address gauge_controller_address = gaugeControllers[token_idx];
if (gauge_controller_address != address(0)) {
rwd_rate = (IFraxGaugeController(gauge_controller_address).global_emission_rate() * last_gauge_relative_weights[token_idx]) / 1e18;
}
else {
rwd_rate = rewardRatesManual[token_idx];
}
}
// Amount of reward tokens per LP token / liquidity unit
function rewardsPerToken() public view returns (uint256[] memory newRewardsPerTokenStored) {
if (_total_liquidity_locked == 0 || _total_combined_weight == 0) {
return rewardsPerTokenStored;
}
else {
newRewardsPerTokenStored = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){
newRewardsPerTokenStored[i] = rewardsPerTokenStored[i] + (
((lastTimeRewardApplicable() - lastUpdateTime) * rewardRates(i) * 1e18) / _total_combined_weight
);
}
return newRewardsPerTokenStored;
}
}
/// @notice The amount of reward tokens an account has earned / accrued
/// @dev In the edge-case of one of the account's stake expiring since the last claim, this will
/// @param account The account to check
/// @return new_earned Array of reward token amounts earned by the account
function earned(address account) public view returns (uint256[] memory new_earned) {
uint256[] memory reward_arr = rewardsPerToken();
new_earned = new uint256[](rewardTokens.length);
if (_combined_weights[account] > 0){
for (uint256 i = 0; i < rewardTokens.length; i++){
new_earned[i] = ((_combined_weights[account] * (reward_arr[i] - userRewardsPerTokenPaid[account][i])) / 1e18)
+ rewards[account][i];
}
}
}
/// @notice The total reward tokens emitted in the given period
/// @return rewards_per_duration_arr Array of reward token amounts emitted in the current period
function getRewardForDuration() external view returns (uint256[] memory rewards_per_duration_arr) {
rewards_per_duration_arr = new uint256[](rewardRatesManual.length);
for (uint256 i = 0; i < rewardRatesManual.length; i++){
rewards_per_duration_arr[i] = rewardRates(i) * rewardsDuration;
}
}
// ------ LIQUIDITY AND WEIGHTS ------
/// @notice The farm's total locked liquidity / LP tokens
/// @return The total locked liquidity
function totalLiquidityLocked() external view returns (uint256) {
return _total_liquidity_locked;
}
/// @notice A user's locked liquidity / LP tokens
/// @param account The address of the account
/// @return The locked liquidity
function lockedLiquidityOf(address account) external view returns (uint256) {
return _locked_liquidity[account];
}
/// @notice The farm's total combined weight of all users
/// @return The total combined weight
function totalCombinedWeight() external view returns (uint256) {
return _total_combined_weight;
}
/// @notice Total 'balance' used for calculating the percent of the pool the account owns
/// @notice Takes into account the locked stake time multiplier and veFXS multiplier
/// @param account The address of the account
/// @return The combined weight
function combinedWeightOf(address account) external view returns (uint256) {
return _combined_weights[account];
}
/// @notice Calculates the combined weight for an account
/// @notice Must be overriden by the child contract
/// @dev account The address of the account
function calcCurCombinedWeight(address account) public virtual view
returns (
uint256 old_combined_weight,
uint256 new_vefxs_multiplier,
uint256 new_combined_weight
)
{
revert("Need cCCW logic");
}
// ------ LOCK RELATED ------
/// @notice Reads the lock boost multiplier for a given duration
/// @param secs The duration of the lock in seconds
/// @return The multiplier amount
function lockMultiplier(uint256 secs) public view returns (uint256) {
return Math.min(
lock_max_multiplier,
(secs * lock_max_multiplier) / lock_time_for_max_multiplier
) ;
}
// ------ FRAX RELATED ------
/// @notice The amount of FRAX denominated value being boosted that an address has staked
/// @param account The address to check
/// @return The amount of FRAX value boosted
function userStakedFrax(address account) public view returns (uint256) {
return (fraxPerLPStored * _locked_liquidity[account]) / MULTIPLIER_PRECISION;
}
/// @notice The amount of FRAX denominated value being boosted that a proxy address has staked
/// @param proxy_address The address to check
/// @return The amount of FRAX value boosted
function proxyStakedFrax(address proxy_address) public view returns (uint256) {
return (fraxPerLPStored * proxy_lp_balances[proxy_address]) / MULTIPLIER_PRECISION;
}
/// @notice The maximum LP that can get max veFXS boosted for a given address at its current veFXS balance
/// @param account The address to check
/// @return The maximum LP that can get max veFXS boosted for a given address at its current veFXS balance
function maxLPForMaxBoost(address account) external view returns (uint256) {
return (veFXS.balanceOf(account) * MULTIPLIER_PRECISION * MULTIPLIER_PRECISION) / (vefxs_per_frax_for_max_boost * fraxPerLPStored);
}
/// @notice Must be overriden to return the current FRAX per LP token
/// @return The current number of FRAX per LP token
function fraxPerLPToken() public virtual view returns (uint256) {
revert("Need fPLPT logic");
}
// ------ veFXS RELATED ------
/// @notice The minimum veFXS required to get max boost for a given address
/// @param account The address to check
/// @return The minimum veFXS required to get max boost
function minVeFXSForMaxBoost(address account) public view returns (uint256) {
return (userStakedFrax(account) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION;
}
/// @notice The minimum veFXS required to get max boost for a given proxy
/// @param proxy_address The proxy address
/// @return The minimum veFXS required to get max boost
function minVeFXSForMaxBoostProxy(address proxy_address) public view returns (uint256) {
return (proxyStakedFrax(proxy_address) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION;
}
/// @notice Looks up a staker's proxy
/// @param addr The address to check
/// @return the_proxy The proxy address, or address(0)
function getProxyFor(address addr) public view returns (address){
if (valid_vefxs_proxies[addr]) {
// If addr itself is a proxy, return that.
// If it farms itself directly, it should use the shared LP tally in proxyStakedFrax
return addr;
}
else {
// Otherwise, return the proxy, or address(0)
return staker_designated_proxies[addr];
}
}
/// @notice The multiplier for a given account, based on veFXS
/// @param account The account to check
/// @return vefxs_multiplier The multiplier boost for the account
function veFXSMultiplier(address account) public view returns (uint256 vefxs_multiplier) {
// Use either the user's or their proxy's veFXS balance
uint256 vefxs_bal_to_use = 0;
address the_proxy = getProxyFor(account);
vefxs_bal_to_use = (the_proxy == address(0)) ? veFXS.balanceOf(account) : veFXS.balanceOf(the_proxy);
// First option based on fraction of total veFXS supply, with an added scale factor
uint256 mult_optn_1 = (vefxs_bal_to_use * vefxs_max_multiplier * vefxs_boost_scale_factor)
/ (veFXS.totalSupply() * MULTIPLIER_PRECISION);
// Second based on old method, where the amount of FRAX staked comes into play
uint256 mult_optn_2;
{
uint256 veFXS_needed_for_max_boost;
// Need to use proxy-wide FRAX balance if applicable, to prevent exploiting
veFXS_needed_for_max_boost = (the_proxy == address(0)) ? minVeFXSForMaxBoost(account) : minVeFXSForMaxBoostProxy(the_proxy);
if (veFXS_needed_for_max_boost > 0){
uint256 user_vefxs_fraction = (vefxs_bal_to_use * MULTIPLIER_PRECISION) / veFXS_needed_for_max_boost;
mult_optn_2 = (user_vefxs_fraction * vefxs_max_multiplier) / MULTIPLIER_PRECISION;
}
else mult_optn_2 = 0; // This will happen with the first stake, when user_staked_frax is 0
}
// Select the higher of the two
vefxs_multiplier = (mult_optn_1 > mult_optn_2 ? mult_optn_1 : mult_optn_2);
// Cap the boost to the vefxs_max_multiplier
if (vefxs_multiplier > vefxs_max_multiplier) vefxs_multiplier = vefxs_max_multiplier;
}
/* =============== MUTATIVE FUNCTIONS =============== */
/// @notice Toggle whether a staker can use the proxy's veFXS balance to boost yields
/// @notice Proxy must call this first, then the staker must call stakerSetVeFXSProxy
function proxyToggleStaker(address staker_address) external {
require(valid_vefxs_proxies[msg.sender], "Invalid proxy");
proxy_allowed_stakers[msg.sender][staker_address] = !proxy_allowed_stakers[msg.sender][staker_address];
// Disable the staker's set proxy if it was the toggler and is currently on
if (staker_designated_proxies[staker_address] == msg.sender){
staker_designated_proxies[staker_address] = address(0);
// Remove the LP as well
proxy_lp_balances[msg.sender] -= _locked_liquidity[staker_address];
}
}
/// @notice After proxy toggles staker to true, staker must call and confirm this
/// @param proxy_address The address of the veFXS proxy
function stakerSetVeFXSProxy(address proxy_address) external {
require(valid_vefxs_proxies[proxy_address], "Invalid proxy");
require(proxy_allowed_stakers[proxy_address][msg.sender], "Proxy has not allowed you yet");
// Corner case sanity check to make sure LP isn't double counted
address old_proxy_addr = staker_designated_proxies[msg.sender];
if (old_proxy_addr != address(0)) {
// Remove the LP count from the old proxy
proxy_lp_balances[old_proxy_addr] -= _locked_liquidity[msg.sender];
}
// Set the new proxy
staker_designated_proxies[msg.sender] = proxy_address;
// Add the the LP as well
proxy_lp_balances[proxy_address] += _locked_liquidity[msg.sender];
}
// ------ STAKING ------
// In children...
// ------ WITHDRAWING ------
// In children...
// ------ REWARDS SYNCING ------
function _updateRewardAndBalance(address account, bool sync_too) internal {
_updateRewardAndBalance(account, sync_too, false);
}
function _updateRewardAndBalance(address account, bool sync_too, bool pre_sync_vemxstored) internal {
// Skip certain functions if we are in an emergency shutdown
if (!withdrawalOnlyShutdown) {
// Need to retro-adjust some things if the period hasn't been renewed, then start a new one
if (sync_too){
sync();
}
}
// Used to make sure the veFXS multiplier is correct if a stake is increased, before calcCurCombinedWeight
if (pre_sync_vemxstored){
_vefxsMultiplierStored[account] = veFXSMultiplier(account);
}
if (account != address(0)) {
// To keep the math correct, the user's combined weight must be recomputed to account for their
// ever-changing veFXS balance.
(
uint256 old_combined_weight,
uint256 new_vefxs_multiplier,
uint256 new_combined_weight
) = calcCurCombinedWeight(account);
// Calculate the earnings first
if (!withdrawalOnlyShutdown) _syncEarned(account);
// Update the user's stored veFXS multipliers
_vefxsMultiplierStored[account] = new_vefxs_multiplier;
// Update the user's and the global combined weights
if (new_combined_weight >= old_combined_weight) {
uint256 weight_diff = new_combined_weight - old_combined_weight;
_total_combined_weight = _total_combined_weight + weight_diff;
_combined_weights[account] = old_combined_weight + weight_diff;
} else {
uint256 weight_diff = old_combined_weight - new_combined_weight;
_total_combined_weight = _total_combined_weight - weight_diff;
_combined_weights[account] = old_combined_weight - weight_diff;
}
}
}
function _syncEarned(address account) internal {
if (account != address(0)) {
// Calculate the earnings
uint256[] memory earned_arr = earned(account);
// Update the rewards array
for (uint256 i = 0; i < earned_arr.length; i++){
rewards[account][i] = earned_arr[i];
}
// Update the rewards paid array
for (uint256 i = 0; i < earned_arr.length; i++){
userRewardsPerTokenPaid[account][i] = rewardsPerTokenStored[i];
}
}
}
// ------ REWARDS CLAIMING ------
/// @notice A function that can be overridden to add extra logic to the getReward function
/// @param destination_address The address to send the rewards to
function getRewardExtraLogic(address destination_address) public nonReentrant {
require(!withdrawalOnlyShutdown, "Only withdrawals allowed");
require(rewardsCollectionPaused == false, "Rewards collection paused");
return _getRewardExtraLogic(msg.sender, destination_address);
}
function _getRewardExtraLogic(address rewardee, address destination_address) internal virtual {
revert("Need gREL logic");
}
// Two different getReward functions are needed because of delegateCall and msg.sender issues
// For backwards-compatibility
/// @notice Claims rewards to destination address
/// @param destination_address The address to send the rewards to
/// @return rewards_before The rewards available before the claim
function getReward(address destination_address) external nonReentrant returns (uint256[] memory) {
return _getReward(msg.sender, destination_address, true);
}
/// @notice Claims rewards to destination address & wether to do extra logic
/// @param destination_address The address to send the rewards to
/// @param claim_extra_too Whether to do extra logic
/// @return rewards_before The rewards available before the claim
function getReward2(address destination_address, bool claim_extra_too) external nonReentrant returns (uint256[] memory) {
return _getReward(msg.sender, destination_address, claim_extra_too);
}
// No withdrawer == msg.sender check needed since this is only internally callable
function _getReward(address rewardee, address destination_address, bool do_extra_logic) internal updateRewardAndBalanceMdf(rewardee, true) returns (uint256[] memory rewards_before) {
// Make sure you are not in shutdown
require(!withdrawalOnlyShutdown, "Only withdrawals allowed");
// Make sure rewards collection isn't paused
require(rewardsCollectionPaused == false, "Rewards collection paused");
// Update the last reward claim time first, as an extra reentrancy safeguard
lastRewardClaimTime[rewardee] = block.timestamp;
// Update the rewards array and distribute rewards
rewards_before = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardTokens.length; i++){
rewards_before[i] = rewards[rewardee][i];
rewards[rewardee][i] = 0;
if (rewards_before[i] > 0) {
TransferHelper.safeTransfer(rewardTokens[i], destination_address, rewards_before[i]);
emit RewardPaid(rewardee, rewards_before[i], rewardTokens[i], destination_address);
}
}
// Handle additional reward logic
if (do_extra_logic) {
_getRewardExtraLogic(rewardee, destination_address);
}
}
// ------ FARM SYNCING ------
// If the period expired, renew it
function retroCatchUp() internal {
// Catch up the old rewards first
_updateStoredRewardsAndTime();
// Pull in rewards from the rewards distributor, if applicable
for (uint256 i = 0; i < rewardDistributors.length; i++){
address reward_distributor_address = rewardDistributors[i];
if (reward_distributor_address != address(0)) {
IFraxGaugeFXSRewardsDistributor(reward_distributor_address).distributeReward(address(this));
}
}
// Ensure the provided reward amount is not more than the balance in the contract.
// This keeps the reward rate in the right range, preventing overflows due to
// very high values of rewardRate in the earned and rewardsPerToken functions;
// Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
uint256 num_periods_elapsed = uint256(block.timestamp - periodFinish) / rewardsDuration; // Floor division to the nearest period
// Make sure there are enough tokens to renew the reward period
for (uint256 i = 0; i < rewardTokens.length; i++){
require((rewardRates(i) * rewardsDuration * (num_periods_elapsed + 1)) <= IERC20(rewardTokens[i]).balanceOf(address(this)), string(abi.encodePacked("Not enough reward tokens available: ", rewardTokens[i])) );
}
// uint256 old_lastUpdateTime = lastUpdateTime;
// uint256 new_lastUpdateTime = block.timestamp;
// lastUpdateTime = periodFinish;
periodFinish = periodFinish + ((num_periods_elapsed + 1) * rewardsDuration);
// Aura & Balancer Gauge Rewards
// ==========================================
// Pull in rewards and set the reward rate for one week, based off of that
// If the rewards get messed up for some reason, set this to 0 and it will skip
// Should only be called once per week max
if (rewardRatesManual[1] != 0) {
// AURA & BAL
// ====================================
uint256 aura_before = IERC20(rewardTokens[1]).balanceOf(address(this));
uint256 bal_before = IERC20(rewardTokens[2]).balanceOf(address(this));
aura_deposit_vault.getReward(address(this), true);
uint256 aura_after = IERC20(rewardTokens[1]).balanceOf(address(this));
uint256 bal_after = IERC20(rewardTokens[2]).balanceOf(address(this));
// Set the new reward rates
rewardRatesManual[1] = (aura_after - aura_before) / rewardsDuration; // AURA
rewardRatesManual[2] = (bal_after - bal_before) / rewardsDuration; // BAL
}
// Bunni oLIT rewards
// ==========================================
// Pull in rewards and set the reward rate for one week, based off of that
// If the rewards get messed up for some reason, set this to 0 and it will skip
// Should only be called once per week max
// if (rewardRatesManual[1] != 0) {
// // oLIT
// // ====================================
// uint256 olit_before = IERC20(rewardTokens[1]).balanceOf(address(this));
// minter.mint(address(stakingToken));
// uint256 olit_after = IERC20(rewardTokens[1]).balanceOf(address(this));
// // Set the new reward rate
// rewardRatesManual[1] = (olit_after - olit_before) / rewardsDuration;
// }
// CONVEX EXTRA REWARDS (OLD METHOD)
// ==========================================
// Pull in rewards and set the reward rate for one week, based off of that
// If the rewards get messed up for some reason, set this to 0 and it will skip
// if (rewardRatesManual[1] != 0 && rewardRatesManual[2] != 0) {
// // CRV & CVX
// // ====================================
// uint256 crv_before = ERC20(rewardTokens[1]).balanceOf(address(this));
// uint256 cvx_before = ERC20(rewardTokens[2]).balanceOf(address(this));
// IConvexBaseRewardPool(0x329cb014b562d5d42927cfF0dEdF4c13ab0442EF).getReward(
// address(this),
// true
// );
// uint256 crv_after = ERC20(rewardTokens[1]).balanceOf(address(this));
// uint256 cvx_after = ERC20(rewardTokens[2]).balanceOf(address(this));
// // Set the new reward rate
// rewardRatesManual[1] = (crv_after - crv_before) / rewardsDuration;
// rewardRatesManual[2] = (cvx_after - cvx_before) / rewardsDuration;
// }
// Make sure everything is caught up again
_updateStoredRewardsAndTime();
}
function _updateStoredRewardsAndTime() internal {
// Get the rewards
uint256[] memory rewards_per_token = rewardsPerToken();
// Update the rewardsPerTokenStored
for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){
rewardsPerTokenStored[i] = rewards_per_token[i];
}
// Update the last stored time
lastUpdateTime = lastTimeRewardApplicable();
}
/// @notice Updates the gauge weights, if applicable
/// @param force_update If true, will update the weights even if the time hasn't elapsed
function sync_gauge_weights(bool force_update) public {
// Loop through the gauge controllers
for (uint256 i = 0; i < gaugeControllers.length; i++){
address gauge_controller_address = gaugeControllers[i];
if (gauge_controller_address != address(0)) {
if (force_update || (block.timestamp > last_gauge_time_totals[i])){
// Update the gauge_relative_weight
last_gauge_relative_weights[i] = IFraxGaugeController(gauge_controller_address).gauge_relative_weight_write(address(this), block.timestamp);
last_gauge_time_totals[i] = IFraxGaugeController(gauge_controller_address).time_total();
}
}
}
}
/// @notice Updates gauge weights, fraxPerLP, pulls in new rewards or updates rewards
function sync() public {
// Make sure you are not in shutdown
require(!withdrawalOnlyShutdown, "Only withdrawals allowed");
// Sync the gauge weight, if applicable
sync_gauge_weights(false);
// Update the fraxPerLPStored
fraxPerLPStored = fraxPerLPToken();
if (block.timestamp >= periodFinish) {
retroCatchUp();
}
else {
_updateStoredRewardsAndTime();
}
}
/* ========== RESTRICTED FUNCTIONS - Curator callable ========== */
// ------ FARM SYNCING ------
// In children...
// ------ PAUSES ------
/// @notice Owner or governance can pause/unpause staking, withdrawals, rewards collection, and collectRewardsOnWithdrawal
/// @param _stakingPaused Whether staking is paused
/// @param _withdrawalsPaused Whether withdrawals are paused
/// @param _rewardsCollectionPaused Whether rewards collection is paused
/// @param _withdrawalOnlyShutdown Whether you can only withdraw. Only settable once
function setPauses(
bool _stakingPaused,
bool _withdrawalsPaused,
bool _rewardsCollectionPaused,
bool _withdrawalOnlyShutdown
) external onlyByOwnGov {
stakingPaused = _stakingPaused;
withdrawalsPaused = _withdrawalsPaused;
rewardsCollectionPaused = _rewardsCollectionPaused;
// Only settable once. Rewards math will be permanently wrong afterwards, so only use
// for recovering LP
if(_withdrawalOnlyShutdown && !withdrawalOnlyShutdown) withdrawalOnlyShutdown = true;
}
/* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */
/// @notice Owner or governance can unlock stakes - irreversible!
function unlockStakes() external onlyByOwnGov {
stakesUnlocked = !stakesUnlocked;
}
/// @notice Owner or governance sets whether an address is a valid veFXS proxy
/// @param _proxy_addr The address to set
function toggleValidVeFXSProxy(address _proxy_addr) external onlyByOwnGov {
valid_vefxs_proxies[_proxy_addr] = !valid_vefxs_proxies[_proxy_addr];
}
/// @notice Allows owner to recover any ERC20 or token manager to recover their reward token.
/// @param tokenAddress The address of the token to recover
/// @param tokenAmount The amount of the token to recover
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) {
// Check if the desired token is a reward token
bool isRewTkn = isRewardToken[tokenAddress];
// Only the reward managers can take back their reward tokens
// Also, other tokens, like the staking token, airdrops, or accidental deposits, can be withdrawn by the owner
if (
(isRewTkn && rewardManagers[tokenAddress] == msg.sender)
|| (!isRewTkn && (msg.sender == owner))
) {
// Aura & Balancer
// Withdraw the tokens from the Aura vault. Do not claim
// =========================================
if (tokenAddress == address(stakingToken)) aura_deposit_vault.withdraw(tokenAmount, false);
TransferHelper.safeTransfer(tokenAddress, msg.sender, tokenAmount);
return;
}
// If none of the above conditions are true
else {
revert("No valid tokens to recover");
}
}
/// @notice Sets multiple variables at once
/// @param _misc_vars The variables to set:
/// [0]: uint256 _lock_max_multiplier,
/// [1] uint256 _vefxs_max_multiplier,
/// [2] uint256 _vefxs_per_frax_for_max_boost,
/// [3] uint256 _vefxs_boost_scale_factor,
/// [4] uint256 _lock_time_for_max_multiplier,
/// [5] uint256 _lock_time_min
/// [6] uint256 _max_stake_limit (must be at greater or equal to old value)
function setMiscVariables(
uint256[6] memory _misc_vars
// [0]: uint256 _lock_max_multiplier,
// [1] uint256 _vefxs_max_multiplier,
// [2] uint256 _vefxs_per_frax_for_max_boost,
// [3] uint256 _vefxs_boost_scale_factor,
// [4] uint256 _lock_time_for_max_multiplier,
// [5] uint256 _lock_time_min
) external onlyByOwnGov {
require(_misc_vars[0] >= MULTIPLIER_PRECISION, "Must be >= MUL PREC");
require((_misc_vars[1] >= 0) && (_misc_vars[2] >= 0) && (_misc_vars[3] >= 0), "Must be >= 0");
require((_misc_vars[4] >= 1) && (_misc_vars[5] >= 1), "Must be >= 1");
lock_max_multiplier = _misc_vars[0];
vefxs_max_multiplier = _misc_vars[1];
vefxs_per_frax_for_max_boost = _misc_vars[2];
vefxs_boost_scale_factor = _misc_vars[3];
lock_time_for_max_multiplier = _misc_vars[4];
lock_time_min = _misc_vars[5];
}
// The owner or the reward token managers can set reward rates
/// @notice Allows owner or reward token managers to set the reward rate for a given reward token
/// @param reward_token_address The address of the reward token
/// @param _new_rate The new reward rate (token amount divided by reward period duration)
/// @param _gauge_controller_address The address of the gauge controller for this reward token
/// @param _rewards_distributor_address The address of the rewards distributor for this reward token
function setRewardVars(address reward_token_address, uint256 _new_rate, address _gauge_controller_address, address _rewards_distributor_address) external onlyTknMgrs(reward_token_address) {
rewardRatesManual[rewardTokenAddrToIdx[reward_token_address]] = _new_rate;
gaugeControllers[rewardTokenAddrToIdx[reward_token_address]] = _gauge_controller_address;
rewardDistributors[rewardTokenAddrToIdx[reward_token_address]] = _rewards_distributor_address;
}
// The owner or the reward token managers can change managers
/// @notice Allows owner or reward token managers to change the reward manager for a given reward token
/// @param reward_token_address The address of the reward token
/// @param new_manager_address The new reward manager address
function changeTokenManager(address reward_token_address, address new_manager_address) external onlyTknMgrs(reward_token_address) {
rewardManagers[reward_token_address] = new_manager_address;
}
/* ========== EVENTS ========== */
event RewardPaid(address indexed user, uint256 amount, address token_address, address destination_address);
/* ========== A CHICKEN ========== */
//
// ,~.
// ,-'__ `-,
// {,-' `. } ,')
// ,( a ) `-.__ ,',')~,
// <=.) ( `-.__,==' ' ' '}
// ( ) /)
// `-'\ , )
// | \ `~. /
// \ `._ \ /
// \ `._____,' ,'
// `-. ,'
// `-._ _,-'
// 77jj'
// //_||
// __//--'/`
// ,--'/` '
//
// [hjw] https://textart.io/art/vw6Sa3iwqIRGkZsN1BC2vweF/chicken
}
// File contracts/Staking/FraxUnifiedFarm_ERC20.sol
// Original license: SPDX_License_Identifier: GPL-2.0-or-later
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ======================= FraxUnifiedFarm_ERC20 ======================
// ====================================================================
// For ERC20 Tokens
// Uses FraxUnifiedFarmTemplate.sol
// -------------------- VARIES --------------------
// Balancer
// import "../Misc_AMOs/balancer/IBalancerGauge.sol";
// Bunni
// import "../Misc_AMOs/bunni/IBunniGauge.sol";
// Convex wrappers
// import "../Curve/ICurvefrxETHETHPool.sol";
// import "../Misc_AMOs/convex/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);
// Aura & Balancer
// Deposit the tokens into the Aura vault
// =========================================
stakingToken.approve(address(aura_deposit_vault), addl_liq);
aura_deposit_vault.stake(addl_liq);
// Update the stake
lockedStakes[msg.sender][theArrayIndex] = LockedStake(
kek_id,
thisStake.start_timestamp,
new_amt,
thisStake.ending_timestamp,
thisStake.lock_multiplier
);
// Update liquidities
_updateLiqAmts(msg.sender, addl_liq, true);
emit LockedAdditional(msg.sender, kek_id, addl_liq);
}
// Extends the lock of an existing stake
function lockLonger(bytes32 kek_id, uint256 new_ending_ts) nonReentrant public {
// Make sure staking isn't paused
require(!stakingPaused, "Staking paused");
// Make sure you are not in shutdown
require(!withdrawalOnlyShutdown, "Only withdrawals allowed");
// Claim rewards at the old balance first
_getReward(msg.sender, msg.sender, true);
// Get the stake and its index
(LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id);
// Check
require(new_ending_ts > block.timestamp, "Must be in the future");
// Calculate some times
uint256 time_left = (thisStake.ending_timestamp > block.timestamp) ? thisStake.ending_timestamp - block.timestamp : 0;
uint256 new_secs = new_ending_ts - block.timestamp;
// Checks
// require(time_left > 0, "Already expired");
require(new_secs > time_left, "Cannot shorten lock time");
require(new_secs >= lock_time_min, "Minimum stake time not met");
require(new_secs <= lock_time_for_max_multiplier, "Trying to lock for too long");
// Update the stake
lockedStakes[msg.sender][theArrayIndex] = LockedStake(
kek_id,
block.timestamp,
thisStake.liquidity,
new_ending_ts,
lockMultiplier(new_secs)
);
// Need to call to update the combined weights
_updateRewardAndBalance(msg.sender, false, true);
emit LockedLonger(msg.sender, kek_id, new_secs, block.timestamp, new_ending_ts);
}
// Two different stake functions are needed because of delegateCall and msg.sender issues (important for proxies)
function stakeLocked(uint256 liquidity, uint256 secs) nonReentrant external returns (bytes32) {
return _stakeLocked(msg.sender, msg.sender, liquidity, secs, block.timestamp);
}
// If this were not internal, and source_address had an infinite approve, this could be exploitable
// (pull funds from source_address and stake for an arbitrary staker_address)
function _stakeLocked(
address staker_address,
address source_address,
uint256 liquidity,
uint256 secs,
uint256 start_timestamp
) internal updateRewardAndBalanceMdf(staker_address, true) returns (bytes32) {
require(!withdrawalOnlyShutdown, "Only withdrawals allowed");
require(!stakingPaused, "Staking paused");
require(secs >= lock_time_min, "Minimum stake time not met");
require(secs <= lock_time_for_max_multiplier,"Trying to lock for too long");
// Pull in the required token(s)
// Varies per farm
TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity);
// Aura & Balancer
// Deposit the tokens into the Aura vault
// =========================================
stakingToken.approve(address(aura_deposit_vault), liquidity);
aura_deposit_vault.stake(liquidity);
// Get the lock multiplier and kek_id
uint256 lock_multiplier = lockMultiplier(secs);
bytes32 kek_id = keccak256(abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address]));
// Create the locked stake
lockedStakes[staker_address].push(LockedStake(
kek_id,
start_timestamp,
liquidity,
start_timestamp + secs,
lock_multiplier
));
// Update liquidities
_updateLiqAmts(staker_address, liquidity, true);
emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address);
return kek_id;
}
// ------ WITHDRAWING ------
/// @notice Withdraw a stake.
/// @param kek_id The id for the stake
/// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless)
/// @dev Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues (important for migration)
function withdrawLocked(bytes32 kek_id, address destination_address, bool claim_rewards_deprecated) nonReentrant external returns (uint256) {
require(withdrawalsPaused == false, "Withdrawals paused");
return _withdrawLocked(msg.sender, destination_address, kek_id, claim_rewards_deprecated);
}
/// @notice No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper functions like withdraw(), migrator_withdraw_unlocked() and migrator_withdraw_locked()
/// @param staker_address The address of the staker
/// @param destination_address Destination address for the withdrawn LP
/// @param kek_id The id for the stake
/// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless)
function _withdrawLocked(
address staker_address,
address destination_address,
bytes32 kek_id,
bool claim_rewards_deprecated
) internal returns (uint256) {
// Collect rewards first and then update the balances
// withdrawalOnlyShutdown to be used in an emergency situation if reward is overemitted or not available
// and the user can forfeit rewards to get their principal back.
if (withdrawalOnlyShutdown) {
// Do nothing.
}
else {
// Get the reward
_getReward(staker_address, destination_address, true);
}
// Get the stake and its index
(LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(staker_address, kek_id);
require(block.timestamp >= thisStake.ending_timestamp || stakesUnlocked == true, "Stake is still locked!");
uint256 liquidity = thisStake.liquidity;
if (liquidity > 0) {
// Aura & Balancer
// Withdraw the tokens from the Aura vault. Do not claim
// =========================================
aura_deposit_vault.withdraw(liquidity, false);
// Give the tokens to the destination_address
// Should throw if insufficient balance
TransferHelper.safeTransfer(address(stakingToken), destination_address, liquidity);
// Remove the stake from the array
delete lockedStakes[staker_address][theArrayIndex];
// Update liquidities
_updateLiqAmts(staker_address, liquidity, false);
emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address);
}
return liquidity;
}
function _getRewardExtraLogic(address rewardee, address destination_address) internal override {
// Do nothing
}
/* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */
// Inherited...
/* ========== EVENTS ========== */
event LockedAdditional(address indexed user, bytes32 kek_id, uint256 amount);
event LockedLonger(address indexed user, bytes32 kek_id, uint256 new_secs, uint256 new_start_ts, uint256 new_end_ts);
event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address);
event WithdrawLocked(address indexed user, uint256 liquidity, bytes32 kek_id, address destination_address);
}
// File contracts/Misc_AMOs/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);
// Aura / Balancer
IComposableStablePool public bal_vanilla_lp_tkn;
IBalancerVault public bal_vanilla_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 = IAuraDeposit(_stakingToken);
bal_vanilla_lp_tkn = IComposableStablePool(0xB06bFBD7b50F80c8d9dA57Fc4cF5CBD5B3E2f148);
bal_vanilla_vault = IBalancerVault(bal_vanilla_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);
}
// Aura & Balancer
// ----------------------------------------
// Nothing
// 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
// Aura / Balancer frxETH-pxETH
// ============================================
{
// Get the pool ID
bytes32 _poolId = bal_vanilla_lp_tkn.getPoolId();
// Get the balances of each token in the pool
( , uint256[] memory balances, ) = bal_vanilla_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
// Balancer vault to Aura deposit vault is 1:1
frax_per_lp_token = (frxETH_usd_value_e36) / bal_vanilla_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":[],"name":"aura_deposit_vault","outputs":[{"internalType":"contract IAuraDepositVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bal_vanilla_lp_tkn","outputs":[{"internalType":"contract IComposableStablePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bal_vanilla_vault","outputs":[{"internalType":"contract IBalancerVault","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"address","name":"account","type":"address"}],"name":"maxLPForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"minVeFXSForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"minVeFXSForMaxBoostProxy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"proxyStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"}],"name":"proxyToggleStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxy_lp_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token_idx","type":"uint256"}],"name":"rewardRates","outputs":[{"internalType":"uint256","name":"rwd_rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint256[]","name":"newRewardsPerTokenStored","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[6]","name":"_misc_vars","type":"uint256[6]"}],"name":"setMiscVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalsPaused","type":"bool"},{"internalType":"bool","name":"_rewardsCollectionPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalOnlyShutdown","type":"bool"}],"name":"setPauses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"uint256","name":"_new_rate","type":"uint256"},{"internalType":"address","name":"_gauge_controller_address","type":"address"},{"internalType":"address","name":"_rewards_distributor_address","type":"address"}],"name":"setRewardVars","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"stakeLocked","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"stakerSetVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"staker_designated_proxies","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakesUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IAuraDeposit","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"force_update","type":"bool"}],"name":"sync_gauge_weights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy_addr","type":"address"}],"name":"toggleValidVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalCombinedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLiquidityLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"userStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"veFXSMultiplier","outputs":[{"internalType":"uint256","name":"vefxs_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_boost_scale_factor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_per_frax_for_max_boost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_rewards_deprecated","type":"bool"}],"name":"withdrawLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalOnlyShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
600480546001600160a01b03191673e557658e3d13d074961265756dc2efb6c903a763179055671bc16d674ec8000060088190556305a39a806009556001600a55673782dace9d900000600b819055600c91909155600d5560c06040526005608090815264189718171b60d91b60a0526025906200007e9082620006ac565b50602880546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b841917905560408051808201909152601281527122a92199182fa1b7b73b32bc2fa7ba3432b960711b6020820152602b90620000dd9082620006ac565b50348015620000eb57600080fd5b5060405162005f1638038062005f168339810160408190526200010e91620008d4565b86868686868686868686868686856001600160a01b038116620001775760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15060016002558451620001e990601290602088019062000546565b508151620001ff90601390602085019062000546565b5080516200021590601490602084019062000546565b5082516200022b906015906020860190620005b0565b5060005b8551811015620003df578060176000888481518110620002535762000253620009db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506001601660008884815181106200029a576200029a620009db565b6020908102919091018101516001600160a01b031682528101919091526040016000908120805460ff191692151592909217909155601880546001810182559082527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e01558451859082908110620003165762000316620009db565b602002602001015160116000888481518110620003375762000337620009db565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601c805460018181019092557f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a21101829055601d805480830182559083527f6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146134f0191909155016200022f565b506024805460ff19169055426007556040805163513872bd60e01b81529051733669c421b77340b2979d1a00a792cc2ee0fce7379163513872bd9160048083019260209291908290030181865afa1580156200043f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004659190620009f1565b6006555050600380546001600160a01b03199081166001600160a01b038f16179091556029805473b06bfbd7b50f80c8d9da57fc4cf5cbd5b3e2f148921682179055604080516311b2515f60e31b81529051919c50638d928af89b5060048082019b5060209a509198508890030195508694508a93505050505afa158015620004f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000518919062000a0b565b602a80546001600160a01b0319166001600160a01b03929092169190911790555062000a3095505050505050565b8280548282559060005260206000209081019282156200059e579160200282015b828111156200059e57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000567565b50620005ac929150620005ee565b5090565b8280548282559060005260206000209081019282156200059e579160200282015b828111156200059e578251825591602001919060010190620005d1565b5b80821115620005ac5760008155600101620005ef565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200063057607f821691505b6020821081036200065157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620006a7576000816000526020600020601f850160051c81016020861015620006825750805b601f850160051c820191505b81811015620006a3578281556001016200068e565b5050505b505050565b81516001600160401b03811115620006c857620006c862000605565b620006e081620006d984546200061b565b8462000657565b602080601f831160018114620007185760008415620006ff5750858301515b600019600386901b1c1916600185901b178555620006a3565b600085815260208120601f198616915b82811015620007495788860151825594840194600190910190840162000728565b5085821015620007685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200079057600080fd5b919050565b604051601f8201601f191681016001600160401b0381118282101715620007c057620007c062000605565b604052919050565b60006001600160401b03821115620007e457620007e462000605565b5060051b60200190565b600082601f8301126200080057600080fd5b81516020620008196200081383620007c8565b62000795565b8083825260208201915060208460051b8701019350868411156200083c57600080fd5b602086015b848110156200086357620008558162000778565b835291830191830162000841565b509695505050505050565b600082601f8301126200088057600080fd5b81516020620008936200081383620007c8565b8083825260208201915060208460051b870101935086841115620008b657600080fd5b602086015b84811015620008635780518352918301918301620008bb565b600080600080600080600060e0888a031215620008f057600080fd5b620008fb8862000778565b60208901519097506001600160401b03808211156200091957600080fd5b620009278b838c01620007ee565b975060408a01519150808211156200093e57600080fd5b6200094c8b838c01620007ee565b965060608a01519150808211156200096357600080fd5b620009718b838c016200086e565b955060808a01519150808211156200098857600080fd5b620009968b838c01620007ee565b945060a08a0151915080821115620009ad57600080fd5b50620009bc8a828b01620007ee565b925050620009cd60c0890162000778565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a0457600080fd5b5051919050565b60006020828403121562000a1e57600080fd5b62000a298262000778565b9392505050565b6154d68062000a406000396000f3fe608060405234801561001057600080fd5b50600436106104715760003560e01c80637f472e5411610250578063cdc82e8011610150578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109db578063facefb64146109ee578063fff6cae914610a0157600080fd5b8063f2a8d349146109bf578063f2caeb1e146109c857600080fd5b8063e1ba95d214610992578063e7f305821461099a578063ebe2b12b146109ad578063f288baf6146109b657600080fd5b8063d5e1a9c61161011f578063d9f96e8d11610104578063d9f96e8d1461094f578063de1a655114610977578063e01f62bf1461098a57600080fd5b8063d5e1a9c614610929578063d7400d561461093c57600080fd5b8063cdc82e80146108f1578063d2010fb4146108fa578063d2fbdc0d14610903578063d42fc9b41461091657600080fd5b8063aa1d4fce116101e3578063c00007b0116101b2578063c8f33c9111610197578063c8f33c91146108ac578063c9d47056146108b5578063ca6df29d146108c857600080fd5b8063c00007b014610886578063c35438261461089957600080fd5b8063aa1d4fce14610859578063b85efd0614610862578063b94c4dcb14610875578063bdb123e31461087e57600080fd5b80638da5cb5b1161021f5780638da5cb5b1461081357806391cf600a146108265780639637927f14610839578063a0f234761461084657600080fd5b80637f472e54146107aa5780638980f11f146107bd57806389b5f00b146107d05780638bad86a7146107e557600080fd5b806341a16f3f116103765780636c430dbb116102ee578063774d4ae7116102bd5780637970833e116102a25780637970833e1461074757806379ba5097146107825780637d6ef08e1461078a57600080fd5b8063774d4ae7146107215780637910d17b1461073457600080fd5b80636c430dbb146106dd5780636e27cef9146106fd57806370641a361461070657806372f702f31461070e57600080fd5b806354fd4d501161034557806364f2c0601161032a57806364f2c060146106a2578063676ad340146106aa57806369339245146106bd57600080fd5b806354fd4d50146106925780635bfd92581461069a57600080fd5b806341a16f3f1461062e57806341edbdf0146106575780634fd2b5361461066c57806353a47bb71461067f57600080fd5b80631face856116104095780632c0c2a0a116103d857806336f89af2116103bd57806336f89af2146105e8578063386a952514610611578063387edc861461061b57600080fd5b80632c0c2a0a146105c25780632df079f1146105d557600080fd5b80631face85614610538578063231b68dc1461054b578063274734141461056e57806328408bab1461059957600080fd5b80631627540c116104455780631627540c146104e857806317b18c89146104fd5780631c1f78eb146105105780631e090f011461051857600080fd5b80628cc262146104765780630238b9361461049f5780630d7bac4f146104c057806312edb24c146104d3575b600080fd5b610489610484366004614cdc565b610a09565b6040516104969190614cf9565b60405180910390f35b6104b26104ad366004614d4b565b610b57565b604051908152602001610496565b6104b26104ce366004614d8d565b610c24565b6104db610c50565b6040516104969190614da6565b6104fb6104f6366004614cdc565b610cb2565b005b6104b261050b366004614de7565b610d9e565b610489610e0e565b61052b610526366004614cdc565b610ea5565b6040516104969190614e09565b6104b2610546366004614cdc565b610f4c565b61055e610559366004614e77565b610f85565b6040519015158152602001610496565b600454610581906001600160a01b031681565b6040516001600160a01b039091168152602001610496565b6105816105a7366004614cdc565b6023602052600090815260409020546001600160a01b031681565b6104b26105d0366004614cdc565b61102a565b6104fb6105e3366004614eb0565b6112d5565b6104b26105f6366004614cdc565b6001600160a01b031660009081526021602052604090205490565b6104b262093a8081565b6104fb610629366004614cdc565b611427565b61058161063c366004614cdc565b6011602052600090815260409020546001600160a01b031681565b61065f611538565b6040516104969190614f30565b6104b261067a366004614cdc565b6115c6565b600154610581906001600160a01b031681565b61065f6115e7565b6104b26115f4565b601f546104b2565b602954610581906001600160a01b031681565b6104b26106cb366004614cdc565b60176020526000908152604090205481565b6104b26106eb366004614cdc565b601b6020526000908152604090205481565b6104b2600a5481565b6104896117ee565b600354610581906001600160a01b031681565b6104b261072f366004614f81565b611943565b610489610742366004614fad565b611b1b565b61075a610755366004614f81565b611b7d565b604080519586526020860194909452928401919091526060830152608082015260a001610496565b6104fb611bcb565b6104b2610798366004614cdc565b60226020526000908152604090205481565b6104b26107b8366004614cdc565b611cd5565b6104fb6107cb366004614f81565b611cec565b60245461055e90640100000000900460ff1681565b6107f86107f3366004614cdc565b611eba565b60408051938452602084019290925290820152606001610496565b600054610581906001600160a01b031681565b6104fb610834366004614cdc565b61208b565b60245461055e9060ff1681565b6104b2610854366004614cdc565b61214a565b6104b2600b5481565b6104fb610870366004614de7565b612207565b6104b260095481565b6104b2612561565b610489610894366004614cdc565b612672565b6105816108a7366004614cdc565b6126e0565b6104b260075481565b602a54610581906001600160a01b031681565b6104b26108d6366004614cdc565b6001600160a01b031660009081526027602052604090205490565b6104b260085481565b6104b260055481565b6104fb610911366004614de7565b612729565b6104b2610924366004614cdc565b612ac0565b6104fb610937366004614fdb565b612aee565b6104fb61094a366004614cdc565b612c68565b6104b261095d366004614cdc565b6001600160a01b0316600090815260208052604090205490565b6104fb610985366004614e77565b612e0e565b601e546104b2565b6104fb612ec1565b6104fb6109a8366004614cdc565b612f6b565b6104b260065481565b6104b2600c5481565b6104b2600d5481565b6104b26109d6366004614d8d565b613098565b6104fb6109e9366004615023565b613195565b6104fb6109fc3660046150be565b61333a565b6104fb61349f565b60606000610a156117ee565b60125490915067ffffffffffffffff811115610a3357610a33615040565b604051908082528060200260200182016040528015610a5c578160200160208202803683370190505b506001600160a01b03841660009081526021602052604090205490925015610b515760005b601254811015610b4f576001600160a01b0384166000818152601a60209081526040808320858452825280832054938352601982528083208584529091529020548351670de0b6b3a76400009190859085908110610ae157610ae161513c565b6020026020010151610af3919061519a565b6001600160a01b038716600090815260216020526040902054610b1691906151ad565b610b2091906151c4565b610b2a91906151ff565b838281518110610b3c57610b3c61513c565b6020908102919091010152600101610a81565b505b50919050565b60006002805403610baf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602454610100900460ff1615610c0b5760405162461bcd60e51b815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610ba6565b610c173384868561352a565b6001600255949350505050565b600854600954600091610c4a91610c3b82866151ad565b610c4591906151c4565b613731565b92915050565b60606012805480602002602001604051908101604052809291908181526020018280548015610ca857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c8a575b5050505050905090565b6000546001600160a01b03163314610d325760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610ba6565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610df15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055610e023380858542613749565b60016002559392505050565b60155460609067ffffffffffffffff811115610e2c57610e2c615040565b604051908082528060200260200182016040528015610e55578160200160208202803683370190505b50905060005b601554811015610ea15762093a80610e7282613098565b610e7c91906151ad565b828281518110610e8e57610e8e61513c565b6020908102919091010152600101610e5b565b5090565b6001600160a01b0381166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f4157838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610edd565b505050509050919050565b6001600160a01b038116600090815260226020526040812054600554670de0b6b3a764000091610f7b916151ad565b610c4a91906151c4565b6001600160a01b03811660009081526016602052604081205460ff16610fad57506000610c4a565b6001600160a01b0383161580610fca57506001600160a01b038216155b15610fd757506000610c4a565b6000546001600160a01b0390811690841603610ff557506001610c4a565b6001600160a01b0382811660009081526011602052604090205481851691160361102157506001610c4a565b50600092915050565b60008080611037846126e0565b90506001600160a01b038116156110e2576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190615212565b611177565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611153573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111779190615212565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b06001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fa9190615212565b61120491906151ad565b600b54600c5461121490866151ad565b61121e91906151ad565b61122891906151c4565b90506000806001600160a01b0384161561124a5761124584611cd5565b611253565b611253876115c6565b905080156112a557600081611270670de0b6b3a7640000886151ad565b61127a91906151c4565b9050670de0b6b3a7640000600c548261129391906151ad565b61129d91906151c4565b9250506112aa565b600091505b508082116112b857806112ba565b815b9450600c548511156112cc57600c5494505b50505050919050565b6000546001600160a01b03163314806113015750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61134d5760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156113ec5750602454640100000000900460ff16155b1561142157602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b60028054036114785760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055602454640100000000900460ff16156114d75760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b60245462010000900460ff16156115305760405162461bcd60e51b815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ba6565b506001600255565b602b80546115459061522b565b80601f01602080910402602001604051908101604052809291908181526020018280546115719061522b565b80156115be5780601f10611593576101008083540402835291602001916115be565b820191906000526020600020905b8154815290600101906020018083116115a157829003601f168201915b505050505081565b6000670de0b6b3a7640000600d546115dd84612ac0565b610f7b91906151ad565b602580546115459061522b565b600080602960009054906101000a90046001600160a01b03166001600160a01b03166338fff2d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561164a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166e9190615212565b602a546040517ff94d4668000000000000000000000000000000000000000000000000000000008152600481018390529192506000916001600160a01b039091169063f94d466890602401600060405180830381865afa1580156116d6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261171c919081019061530b565b509150506000816001815181106117355761173561513c565b602002602001015190506000611749612561565b61175390836151ad565b611762906402540be4006151ad565b9050602960009054906101000a90046001600160a01b03166001600160a01b031663876f303b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117db9190615212565b6117e590826151c4565b94505050505090565b6060601e54600014806118015750601f54155b1561185b576018805480602002602001604051908101604052809291908181526020018280548015610ca857602002820191906000526020600020905b81548152602001906001019080831161183e575050505050905090565b60125467ffffffffffffffff81111561187657611876615040565b60405190808252806020026020018201604052801561189f578160200160208202803683370190505b50905060005b601854811015610ea157601f546118bb82613098565b6007546118c6613b88565b6118d0919061519a565b6118da91906151ad565b6118ec90670de0b6b3a76400006151ad565b6118f691906151c4565b601882815481106119095761190961513c565b906000526020600020015461191e91906151ff565b8282815181106119305761193061513c565b60209081029190910101526001016118a5565b6001600160a01b03821660009081526027602052604081208054829190849081106119705761197061513c565b600091825260208083206040805160a08101825260059094029091018054845260018101548484018190526002820154858401526003820154606086015260049091015460808501526001600160a01b0389168552601b90925283205491935011156119e1575060208101516119fc565b506001600160a01b0384166000908152601b60205260409020545b42826060015111611aaf5760608201516001600160a01b0386166000908152601b60205260409020541015611aa6576000818360600151611a3d919061519a565b90506000836060015142611a51919061519a565b90506000611a636104ce6002856151c4565b90506000611a7183826151ad565b611a7b85846151ad565b611a8591906151ff565b9050611a9183856151ff565b611a9b90826151c4565b965050505050611aff565b60009250611aff565b600080828460600151611ac2919061519a565b90506000428560600151611ad6919061519a565b90506002611ae482846151ff565b611aee91906151c4565b92505050611afb81610c24565b9350505b8160800151831115611b1357816080015192505b505092915050565b60606002805403611b6e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055610e02338484613b9b565b60276020528160005260406000208181548110611b9957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b6001546001600160a01b03163314611c4b5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610ba6565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03841617909155169055565b6000670de0b6b3a7640000600d546115dd84610f4c565b60005482906001600160a01b0316331480611d0c5750611d0c3382610f85565b611d585760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b6001600160a01b03831660009081526016602052604090205460ff16808015611d9a57506001600160a01b038481166000908152601160205260409020541633145b80611db8575080158015611db857506000546001600160a01b031633145b15611e6d576003546001600160a01b0390811690851603611e6257600480546040517f38d07436000000000000000000000000000000000000000000000000000000008152918201859052600060248301526001600160a01b0316906338d07436906044016020604051808303816000875af1158015611e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6091906153d9565b505b611421843385613e52565b60405162461bcd60e51b815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610ba6565b505050565b6001600160a01b0381166000908152602160205260408120549080611ede8461102a565b6001600160a01b038516600090815260208052604081205491935090158015611f1d57506001600160a01b038516600090815260216020526040902054155b80611f4057506001600160a01b0385166000908152600e60205260409020548310155b15611f4c575081611f7f565b6001600160a01b0385166000908152600e6020526040902054600290611f7290856151ff565b611f7c91906151c4565b90505b6000915060005b6001600160a01b038616600090815260276020526040902054811015612082576001600160a01b0386166000908152602760205260408120805483908110611fd057611fd061513c565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006120298884611943565b60408301519091506000670de0b6b3a764000061204687856151ff565b61205090846151ad565b61205a91906151c4565b61206490836151ff565b905061207081886151ff565b96505060019093019250611f86915050565b50509193909250565b6000546001600160a01b03163314806120b75750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6121035760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b6001600160a01b03166000908152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600554600d5461215c91906151ad565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156121d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121fd9190615212565b6115dd91906151ad565b60028054036122585760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556024546301000000900460ff16156122b65760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b602454640100000000900460ff16156123115760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b61231d33336001613b9b565b5060008061232b3385613f9b565b91509150600083836040015161234191906151ff565b905060035461235b906001600160a01b0316333087614128565b600354600480546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0391821692810192909252602482018790529091169063095ea7b3906044016020604051808303816000875af11580156123cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f191906153d9565b50600480546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081529182018690526001600160a01b03169063a694fc3a906024016020604051808303816000875af1158015612454573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247891906153d9565b506040805160a0810182528681526020858101518183015281830184905260608087015190830152608080870151908301523360009081526027909152919091208054849081106124cb576124cb61513c565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505061251a3385600161429f565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156125bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e09190615410565b945094505093509350600083121580156125f957508115155b801561261d57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b6126695760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610ba6565b50909392505050565b606060028054036126c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556126d533836001613b9b565b600160025592915050565b6001600160a01b0381166000908152600f602052604081205460ff1615612705575090565b506001600160a01b039081166000908152602360205260409020541690565b919050565b600280540361277a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556024546301000000900460ff16156127d85760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b602454640100000000900460ff16156128335760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b61283f33336001613b9b565b5060008061284d3385613f9b565b915091504283116128a05760405162461bcd60e51b815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610ba6565b6000428360600151116128b45760006128c4565b4283606001516128c4919061519a565b905060006128d2428661519a565b90508181116129235760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610ba6565b600a548110156129755760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ba6565b6009548111156129c75760405162461bcd60e51b815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ba6565b6040518060a00160405280878152602001428152602001856040015181526020018681526020016129f783610c24565b9052336000908152602760205260409020805485908110612a1a57612a1a61513c565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612a6a33600060016143c0565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b6001600160a01b0381166000908152602080526040812054600554670de0b6b3a764000091610f7b916151ad565b60005484906001600160a01b0316331480612b0e5750612b0e3382610f85565b612b5a5760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b6001600160a01b038516600090815260176020526040902054601580548692908110612b8857612b8861513c565b906000526020600020018190555082601360176000886001600160a01b03166001600160a01b031681526020019081526020016000205481548110612bcf57612bcf61513c565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055918716815260179091526040902054601480548492908110612c3357612c3361513c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050505050565b6001600160a01b0381166000908152600f602052604090205460ff16612cd05760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ba6565b6001600160a01b038116600090815260106020908152604080832033845290915290205460ff16612d435760405162461bcd60e51b815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610ba6565b336000908152602360205260409020546001600160a01b03168015612d9d5733600090815260208080526040808320546001600160a01b038516845260229092528220805491929091612d9790849061519a565b90915550505b33600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387169081179091558280528184205490845260229092528220805491929091612e059084906151ff565b90915550505050565b60005482906001600160a01b0316331480612e2e5750612e2e3382610f85565b612e7a5760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b506001600160a01b03918216600090815260116020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6000546001600160a01b0316331480612eed5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612f395760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600f602052604090205460ff16612fca5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ba6565b3360008181526010602090815260408083206001600160a01b038681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603613095576001600160a01b038116600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055818052808320543384526022909252822080549192909161308f90849061519a565b90915550505b50565b600080601383815481106130ae576130ae61513c565b6000918252602090912001546001600160a01b03169050801561316f57670de0b6b3a7640000601c84815481106130e7576130e761513c565b9060005260206000200154826001600160a01b0316630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613130573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131549190615212565b61315e91906151ad565b61316891906151c4565b9150610b51565b601583815481106131825761318261513c565b9060005260206000200154915050919050565b60005b601354811015613336576000601382815481106131b7576131b761513c565b6000918252602090912001546001600160a01b03169050801561332d5782806131fc5750601d82815481106131ee576131ee61513c565b906000526020600020015442115b1561332d576040517f6472eee10000000000000000000000000000000000000000000000000000000081523060048201524260248201526001600160a01b03821690636472eee1906044016020604051808303816000875af1158015613266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061328a9190615212565b601c838154811061329d5761329d61513c565b9060005260206000200181905550806001600160a01b031663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330d9190615212565b601d83815481106133205761332061513c565b6000918252602090912001555b50600101613198565b5050565b6000546001600160a01b03163314806133665750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6133b25760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b8051670de0b6b3a7640000111561340b5760405162461bcd60e51b815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610ba6565b6080810151600111801590613425575060a0810151600111155b6134715760405162461bcd60e51b815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610ba6565b80516008556020810151600c556040810151600d556060810151600b55608081015160095560a00151600a55565b602454640100000000900460ff16156134fa5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b6135046000613195565b61350c6115f4565b6005556006544210613522576135206144fe565b565b613520614b99565b602454600090640100000000900460ff1661354d5761354b85856001613b9b565b505b60008061355a8786613f9b565b91509150816060015142101580613578575060245460ff1615156001145b6135c45760405162461bcd60e51b815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610ba6565b6040820151801561372657600480546040517f38d07436000000000000000000000000000000000000000000000000000000008152918201839052600060248301526001600160a01b0316906338d07436906044016020604051808303816000875af1158015613638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365c91906153d9565b50600354613674906001600160a01b03168883613e52565b6001600160a01b038816600090815260276020526040902080548390811061369e5761369e61513c565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556136d8908990839061429f565b60408051828152602081018890526001600160a01b03898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b60008183106137405781613742565b825b9392505050565b600085600161375a828260006143c0565b602454640100000000900460ff16156137b55760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b6024546301000000900460ff161561380f5760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b600a548510156138615760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ba6565b6009548511156138b35760405162461bcd60e51b815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ba6565b6003546138cb906001600160a01b0316883089614128565b600354600480546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0391821692810192909252602482018990529091169063095ea7b3906044016020604051808303816000875af115801561393d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396191906153d9565b50600480546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081529182018890526001600160a01b03169063a694fc3a906024016020604051808303816000875af11580156139c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139e891906153d9565b5060006139f486610c24565b6001600160a01b038a166000908152602080805260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206001600160a01b038e1660009081526027835283902060a0850184528185529184018a90529183018b90529092509060608101613acb8a8a6151ff565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613b27908b908a9061429f565b60408051898152602081018990529081018290526001600160a01b038a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b6000613b9642600654613731565b905090565b6060836001613bac828260006143c0565b602454640100000000900460ff1615613c075760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b60245462010000900460ff1615613c605760405162461bcd60e51b815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ba6565b6001600160a01b0386166000908152601b6020526040902042905560125467ffffffffffffffff811115613c9657613c96615040565b604051908082528060200260200182016040528015613cbf578160200160208202803683370190505b50925060005b601254811015613e48576001600160a01b0387166000908152601a602090815260408083208484529091529020548451859083908110613d0757613d0761513c565b6020908102919091018101919091526001600160a01b0388166000908152601a825260408082208483529092529081208190558451859083908110613d4e57613d4e61513c565b60200260200101511115613e4057613db060128281548110613d7257613d7261513c565b9060005260206000200160009054906101000a90046001600160a01b031687868481518110613da357613da361513c565b6020026020010151613e52565b866001600160a01b03167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613ded57613ded61513c565b602002602001015160128481548110613e0857613e0861513c565b60009182526020918290200154604080519384526001600160a01b03918216928401929092528a169082015260600160405180910390a25b600101613cc5565b5050509392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613edc9190615460565b6000604051808303816000865af19150503d8060008114613f19576040519150601f19603f3d011682016040523d82523d6000602084013e613f1e565b606091505b5091509150818015613f48575080511580613f48575080806020019051810190613f4891906153d9565b613f945760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610ba6565b5050505050565b613fd06040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156140c65760005b6001600160a01b0385166000908152602760205260409020548110156140c4576001600160a01b03851660009081526027602052604090208054829081106140255761402561513c565b90600052602060002090600502016000015484036140bc576001600160a01b03851660009081526027602052604090208054829081106140675761406761513c565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506140c4565b600101613fdb565b505b82158015906140d55750815183145b6141215760405162461bcd60e51b815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610ba6565b9250929050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916141ba9190615460565b6000604051808303816000865af19150503d80600081146141f7576040519150601f19603f3d011682016040523d82523d6000602084013e6141fc565b606091505b509150915081801561422657508051158061422657508080602001905181019061422691906153d9565b6142975760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610ba6565b505050505050565b60006142aa846126e0565b905081156143375782601e60008282546142c491906151ff565b90915550506001600160a01b0384166000908152602080526040812080548592906142f09084906151ff565b90915550506001600160a01b03811615614332576001600160a01b0381166000908152602260205260408120805485929061432c9084906151ff565b90915550505b6143b7565b82601e6000828254614349919061519a565b90915550506001600160a01b03841660009081526020805260408120805485929061437590849061519a565b90915550506001600160a01b038116156143b7576001600160a01b038116600090815260226020526040812080548592906143b190849061519a565b90915550505b61142184600060015b602454640100000000900460ff166143e05781156143e0576143e061349f565b8015614409576143ef8361102a565b6001600160a01b0384166000908152600e60205260409020555b6001600160a01b03831615611eb557600080600061442686611eba565b6024549295509093509150640100000000900460ff166144495761444986614c02565b6001600160a01b0386166000908152600e602052604090208290558281106144b3576000614477848361519a565b905080601f5461448791906151ff565b601f5561449481856151ff565b6001600160a01b03881660009081526021602052604090205550614297565b60006144bf828561519a565b905080601f546144cf919061519a565b601f556144dc818561519a565b6001600160a01b03881660009081526021602052604090205550505050505050565b614506614b99565b60005b6014548110156145d3576000601482815481106145285761452861513c565b6000918252602090912001546001600160a01b0316905080156145ca576040517f092193ab0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063092193ab9060240160408051808303816000875af11580156145a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c7919061547c565b50505b50600101614509565b50600062093a80600654426145e8919061519a565b6145f291906151c4565b905060005b6012548110156147a457601281815481106146145761461461513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561467e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146a29190615212565b6146ad8360016151ff565b62093a806146ba84613098565b6146c491906151ad565b6146ce91906151ad565b1115601282815481106146e3576146e361513c565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660448201526058016040516020818303038152906040529061479b5760405162461bcd60e51b8152600401610ba69190614f30565b506001016145f7565b5062093a806147b48260016151ff565b6147be91906151ad565b6006546147cb91906151ff565b6006556015805460019081106147e3576147e361513c565b9060005260206000200154600014614b95576000601260018154811061480b5761480b61513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614875573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148999190615212565b9050600060126002815481106148b1576148b161513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561491b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061493f9190615212565b600480546040517f7050ccd90000000000000000000000000000000000000000000000000000000081523092810192909252600160248301529192506001600160a01b0390911690637050ccd9906044016020604051808303816000875af11580156149af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149d391906153d9565b50600060126001815481106149ea576149ea61513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614a54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a789190615212565b905060006012600281548110614a9057614a9061513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1e9190615212565b905062093a80614b2e858461519a565b614b3891906151c4565b6015600181548110614b4c57614b4c61513c565b60009182526020909120015562093a80614b66848361519a565b614b7091906151c4565b6015600281548110614b8457614b8461513c565b600091825260209091200155505050505b6130955b6000614ba36117ee565b905060005b601854811015614bf357818181518110614bc457614bc461513c565b602002602001015160188281548110614bdf57614bdf61513c565b600091825260209091200155600101614ba8565b50614bfc613b88565b60075550565b6001600160a01b03811615613095576000614c1c82610a09565b905060005b8151811015614c7357818181518110614c3c57614c3c61513c565b6020908102919091018101516001600160a01b0385166000908152601a835260408082208583529093529190912055600101614c21565b5060005b8151811015611eb55760188181548110614c9357614c9361513c565b60009182526020808320909101546001600160a01b0386168352601982526040808420858552909252912055600101614c77565b6001600160a01b038116811461309557600080fd5b600060208284031215614cee57600080fd5b813561374281614cc7565b6020808252825182820181905260009190848201906040850190845b81811015614d3157835183529284019291840191600101614d15565b50909695505050505050565b801515811461309557600080fd5b600080600060608486031215614d6057600080fd5b833592506020840135614d7281614cc7565b91506040840135614d8281614d3d565b809150509250925092565b600060208284031215614d9f57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d315783516001600160a01b031683529284019291840191600101614dc2565b60008060408385031215614dfa57600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e6a5781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614e26565b5091979650505050505050565b60008060408385031215614e8a57600080fd5b8235614e9581614cc7565b91506020830135614ea581614cc7565b809150509250929050565b60008060008060808587031215614ec657600080fd5b8435614ed181614d3d565b93506020850135614ee181614d3d565b92506040850135614ef181614d3d565b91506060850135614f0181614d3d565b939692955090935050565b60005b83811015614f27578181015183820152602001614f0f565b50506000910152565b6020815260008251806020840152614f4f816040850160208701614f0c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614f9457600080fd5b8235614f9f81614cc7565b946020939093013593505050565b60008060408385031215614fc057600080fd5b8235614fcb81614cc7565b91506020830135614ea581614d3d565b60008060008060808587031215614ff157600080fd5b8435614ffc81614cc7565b935060208501359250604085013561501381614cc7565b91506060850135614f0181614cc7565b60006020828403121561503557600080fd5b813561374281614d3d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156150b6576150b6615040565b604052919050565b600060c082840312156150d057600080fd5b82601f8301126150df57600080fd5b60405160c0810181811067ffffffffffffffff8211171561510257615102615040565b6040528060c084018581111561511757600080fd5b845b81811015615131578035835260209283019201615119565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610c4a57610c4a61516b565b8082028115828204841417610c4a57610c4a61516b565b6000826151fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610c4a57610c4a61516b565b60006020828403121561522457600080fd5b5051919050565b600181811c9082168061523f57607f821691505b602082108103610b51577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600067ffffffffffffffff82111561529257615292615040565b5060051b60200190565b600082601f8301126152ad57600080fd5b815160206152c26152bd83615278565b61506f565b8083825260208201915060208460051b8701019350868411156152e457600080fd5b602086015b8481101561530057805183529183019183016152e9565b509695505050505050565b60008060006060848603121561532057600080fd5b835167ffffffffffffffff8082111561533857600080fd5b818601915086601f83011261534c57600080fd5b8151602061535c6152bd83615278565b82815260059290921b8401810191818101908a84111561537b57600080fd5b948201945b838610156153a257855161539381614cc7565b82529482019490820190615380565b918901519197509093505050808211156153bb57600080fd5b506153c88682870161529c565b925050604084015190509250925092565b6000602082840312156153eb57600080fd5b815161374281614d3d565b805169ffffffffffffffffffff8116811461272457600080fd5b600080600080600060a0868803121561542857600080fd5b615431866153f6565b9450602086015193506040860151925060608601519150615454608087016153f6565b90509295509295909350565b60008251615472818460208701614f0c565b9190910192915050565b6000806040838503121561548f57600080fd5b50508051602090910151909290915056fea26469706673582212203224042895f099e06381ae413bdb9836d4967292f17612d7df8e1595a897805a64736f6c63430008170033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000004a4ef6be54d2666a6d56cf861de7ab3d150a20b600000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000c0c293ce456ff0ed870add98a0828dd4d2903dbf000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000002e90edd00000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104715760003560e01c80637f472e5411610250578063cdc82e8011610150578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109db578063facefb64146109ee578063fff6cae914610a0157600080fd5b8063f2a8d349146109bf578063f2caeb1e146109c857600080fd5b8063e1ba95d214610992578063e7f305821461099a578063ebe2b12b146109ad578063f288baf6146109b657600080fd5b8063d5e1a9c61161011f578063d9f96e8d11610104578063d9f96e8d1461094f578063de1a655114610977578063e01f62bf1461098a57600080fd5b8063d5e1a9c614610929578063d7400d561461093c57600080fd5b8063cdc82e80146108f1578063d2010fb4146108fa578063d2fbdc0d14610903578063d42fc9b41461091657600080fd5b8063aa1d4fce116101e3578063c00007b0116101b2578063c8f33c9111610197578063c8f33c91146108ac578063c9d47056146108b5578063ca6df29d146108c857600080fd5b8063c00007b014610886578063c35438261461089957600080fd5b8063aa1d4fce14610859578063b85efd0614610862578063b94c4dcb14610875578063bdb123e31461087e57600080fd5b80638da5cb5b1161021f5780638da5cb5b1461081357806391cf600a146108265780639637927f14610839578063a0f234761461084657600080fd5b80637f472e54146107aa5780638980f11f146107bd57806389b5f00b146107d05780638bad86a7146107e557600080fd5b806341a16f3f116103765780636c430dbb116102ee578063774d4ae7116102bd5780637970833e116102a25780637970833e1461074757806379ba5097146107825780637d6ef08e1461078a57600080fd5b8063774d4ae7146107215780637910d17b1461073457600080fd5b80636c430dbb146106dd5780636e27cef9146106fd57806370641a361461070657806372f702f31461070e57600080fd5b806354fd4d501161034557806364f2c0601161032a57806364f2c060146106a2578063676ad340146106aa57806369339245146106bd57600080fd5b806354fd4d50146106925780635bfd92581461069a57600080fd5b806341a16f3f1461062e57806341edbdf0146106575780634fd2b5361461066c57806353a47bb71461067f57600080fd5b80631face856116104095780632c0c2a0a116103d857806336f89af2116103bd57806336f89af2146105e8578063386a952514610611578063387edc861461061b57600080fd5b80632c0c2a0a146105c25780632df079f1146105d557600080fd5b80631face85614610538578063231b68dc1461054b578063274734141461056e57806328408bab1461059957600080fd5b80631627540c116104455780631627540c146104e857806317b18c89146104fd5780631c1f78eb146105105780631e090f011461051857600080fd5b80628cc262146104765780630238b9361461049f5780630d7bac4f146104c057806312edb24c146104d3575b600080fd5b610489610484366004614cdc565b610a09565b6040516104969190614cf9565b60405180910390f35b6104b26104ad366004614d4b565b610b57565b604051908152602001610496565b6104b26104ce366004614d8d565b610c24565b6104db610c50565b6040516104969190614da6565b6104fb6104f6366004614cdc565b610cb2565b005b6104b261050b366004614de7565b610d9e565b610489610e0e565b61052b610526366004614cdc565b610ea5565b6040516104969190614e09565b6104b2610546366004614cdc565b610f4c565b61055e610559366004614e77565b610f85565b6040519015158152602001610496565b600454610581906001600160a01b031681565b6040516001600160a01b039091168152602001610496565b6105816105a7366004614cdc565b6023602052600090815260409020546001600160a01b031681565b6104b26105d0366004614cdc565b61102a565b6104fb6105e3366004614eb0565b6112d5565b6104b26105f6366004614cdc565b6001600160a01b031660009081526021602052604090205490565b6104b262093a8081565b6104fb610629366004614cdc565b611427565b61058161063c366004614cdc565b6011602052600090815260409020546001600160a01b031681565b61065f611538565b6040516104969190614f30565b6104b261067a366004614cdc565b6115c6565b600154610581906001600160a01b031681565b61065f6115e7565b6104b26115f4565b601f546104b2565b602954610581906001600160a01b031681565b6104b26106cb366004614cdc565b60176020526000908152604090205481565b6104b26106eb366004614cdc565b601b6020526000908152604090205481565b6104b2600a5481565b6104896117ee565b600354610581906001600160a01b031681565b6104b261072f366004614f81565b611943565b610489610742366004614fad565b611b1b565b61075a610755366004614f81565b611b7d565b604080519586526020860194909452928401919091526060830152608082015260a001610496565b6104fb611bcb565b6104b2610798366004614cdc565b60226020526000908152604090205481565b6104b26107b8366004614cdc565b611cd5565b6104fb6107cb366004614f81565b611cec565b60245461055e90640100000000900460ff1681565b6107f86107f3366004614cdc565b611eba565b60408051938452602084019290925290820152606001610496565b600054610581906001600160a01b031681565b6104fb610834366004614cdc565b61208b565b60245461055e9060ff1681565b6104b2610854366004614cdc565b61214a565b6104b2600b5481565b6104fb610870366004614de7565b612207565b6104b260095481565b6104b2612561565b610489610894366004614cdc565b612672565b6105816108a7366004614cdc565b6126e0565b6104b260075481565b602a54610581906001600160a01b031681565b6104b26108d6366004614cdc565b6001600160a01b031660009081526027602052604090205490565b6104b260085481565b6104b260055481565b6104fb610911366004614de7565b612729565b6104b2610924366004614cdc565b612ac0565b6104fb610937366004614fdb565b612aee565b6104fb61094a366004614cdc565b612c68565b6104b261095d366004614cdc565b6001600160a01b0316600090815260208052604090205490565b6104fb610985366004614e77565b612e0e565b601e546104b2565b6104fb612ec1565b6104fb6109a8366004614cdc565b612f6b565b6104b260065481565b6104b2600c5481565b6104b2600d5481565b6104b26109d6366004614d8d565b613098565b6104fb6109e9366004615023565b613195565b6104fb6109fc3660046150be565b61333a565b6104fb61349f565b60606000610a156117ee565b60125490915067ffffffffffffffff811115610a3357610a33615040565b604051908082528060200260200182016040528015610a5c578160200160208202803683370190505b506001600160a01b03841660009081526021602052604090205490925015610b515760005b601254811015610b4f576001600160a01b0384166000818152601a60209081526040808320858452825280832054938352601982528083208584529091529020548351670de0b6b3a76400009190859085908110610ae157610ae161513c565b6020026020010151610af3919061519a565b6001600160a01b038716600090815260216020526040902054610b1691906151ad565b610b2091906151c4565b610b2a91906151ff565b838281518110610b3c57610b3c61513c565b6020908102919091010152600101610a81565b505b50919050565b60006002805403610baf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602454610100900460ff1615610c0b5760405162461bcd60e51b815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610ba6565b610c173384868561352a565b6001600255949350505050565b600854600954600091610c4a91610c3b82866151ad565b610c4591906151c4565b613731565b92915050565b60606012805480602002602001604051908101604052809291908181526020018280548015610ca857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c8a575b5050505050905090565b6000546001600160a01b03163314610d325760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610ba6565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610df15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055610e023380858542613749565b60016002559392505050565b60155460609067ffffffffffffffff811115610e2c57610e2c615040565b604051908082528060200260200182016040528015610e55578160200160208202803683370190505b50905060005b601554811015610ea15762093a80610e7282613098565b610e7c91906151ad565b828281518110610e8e57610e8e61513c565b6020908102919091010152600101610e5b565b5090565b6001600160a01b0381166000908152602760209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f4157838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610edd565b505050509050919050565b6001600160a01b038116600090815260226020526040812054600554670de0b6b3a764000091610f7b916151ad565b610c4a91906151c4565b6001600160a01b03811660009081526016602052604081205460ff16610fad57506000610c4a565b6001600160a01b0383161580610fca57506001600160a01b038216155b15610fd757506000610c4a565b6000546001600160a01b0390811690841603610ff557506001610c4a565b6001600160a01b0382811660009081526011602052604090205481851691160361102157506001610c4a565b50600092915050565b60008080611037846126e0565b90506001600160a01b038116156110e2576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190615212565b611177565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611153573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111779190615212565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b06001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fa9190615212565b61120491906151ad565b600b54600c5461121490866151ad565b61121e91906151ad565b61122891906151c4565b90506000806001600160a01b0384161561124a5761124584611cd5565b611253565b611253876115c6565b905080156112a557600081611270670de0b6b3a7640000886151ad565b61127a91906151c4565b9050670de0b6b3a7640000600c548261129391906151ad565b61129d91906151c4565b9250506112aa565b600091505b508082116112b857806112ba565b815b9450600c548511156112cc57600c5494505b50505050919050565b6000546001600160a01b03163314806113015750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61134d5760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156113ec5750602454640100000000900460ff16155b1561142157602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b60028054036114785760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055602454640100000000900460ff16156114d75760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b60245462010000900460ff16156115305760405162461bcd60e51b815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ba6565b506001600255565b602b80546115459061522b565b80601f01602080910402602001604051908101604052809291908181526020018280546115719061522b565b80156115be5780601f10611593576101008083540402835291602001916115be565b820191906000526020600020905b8154815290600101906020018083116115a157829003601f168201915b505050505081565b6000670de0b6b3a7640000600d546115dd84612ac0565b610f7b91906151ad565b602580546115459061522b565b600080602960009054906101000a90046001600160a01b03166001600160a01b03166338fff2d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561164a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166e9190615212565b602a546040517ff94d4668000000000000000000000000000000000000000000000000000000008152600481018390529192506000916001600160a01b039091169063f94d466890602401600060405180830381865afa1580156116d6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261171c919081019061530b565b509150506000816001815181106117355761173561513c565b602002602001015190506000611749612561565b61175390836151ad565b611762906402540be4006151ad565b9050602960009054906101000a90046001600160a01b03166001600160a01b031663876f303b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117db9190615212565b6117e590826151c4565b94505050505090565b6060601e54600014806118015750601f54155b1561185b576018805480602002602001604051908101604052809291908181526020018280548015610ca857602002820191906000526020600020905b81548152602001906001019080831161183e575050505050905090565b60125467ffffffffffffffff81111561187657611876615040565b60405190808252806020026020018201604052801561189f578160200160208202803683370190505b50905060005b601854811015610ea157601f546118bb82613098565b6007546118c6613b88565b6118d0919061519a565b6118da91906151ad565b6118ec90670de0b6b3a76400006151ad565b6118f691906151c4565b601882815481106119095761190961513c565b906000526020600020015461191e91906151ff565b8282815181106119305761193061513c565b60209081029190910101526001016118a5565b6001600160a01b03821660009081526027602052604081208054829190849081106119705761197061513c565b600091825260208083206040805160a08101825260059094029091018054845260018101548484018190526002820154858401526003820154606086015260049091015460808501526001600160a01b0389168552601b90925283205491935011156119e1575060208101516119fc565b506001600160a01b0384166000908152601b60205260409020545b42826060015111611aaf5760608201516001600160a01b0386166000908152601b60205260409020541015611aa6576000818360600151611a3d919061519a565b90506000836060015142611a51919061519a565b90506000611a636104ce6002856151c4565b90506000611a7183826151ad565b611a7b85846151ad565b611a8591906151ff565b9050611a9183856151ff565b611a9b90826151c4565b965050505050611aff565b60009250611aff565b600080828460600151611ac2919061519a565b90506000428560600151611ad6919061519a565b90506002611ae482846151ff565b611aee91906151c4565b92505050611afb81610c24565b9350505b8160800151831115611b1357816080015192505b505092915050565b60606002805403611b6e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b60028055610e02338484613b9b565b60276020528160005260406000208181548110611b9957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b6001546001600160a01b03163314611c4b5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610ba6565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03841617909155169055565b6000670de0b6b3a7640000600d546115dd84610f4c565b60005482906001600160a01b0316331480611d0c5750611d0c3382610f85565b611d585760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b6001600160a01b03831660009081526016602052604090205460ff16808015611d9a57506001600160a01b038481166000908152601160205260409020541633145b80611db8575080158015611db857506000546001600160a01b031633145b15611e6d576003546001600160a01b0390811690851603611e6257600480546040517f38d07436000000000000000000000000000000000000000000000000000000008152918201859052600060248301526001600160a01b0316906338d07436906044016020604051808303816000875af1158015611e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6091906153d9565b505b611421843385613e52565b60405162461bcd60e51b815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610ba6565b505050565b6001600160a01b0381166000908152602160205260408120549080611ede8461102a565b6001600160a01b038516600090815260208052604081205491935090158015611f1d57506001600160a01b038516600090815260216020526040902054155b80611f4057506001600160a01b0385166000908152600e60205260409020548310155b15611f4c575081611f7f565b6001600160a01b0385166000908152600e6020526040902054600290611f7290856151ff565b611f7c91906151c4565b90505b6000915060005b6001600160a01b038616600090815260276020526040902054811015612082576001600160a01b0386166000908152602760205260408120805483908110611fd057611fd061513c565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006120298884611943565b60408301519091506000670de0b6b3a764000061204687856151ff565b61205090846151ad565b61205a91906151c4565b61206490836151ff565b905061207081886151ff565b96505060019093019250611f86915050565b50509193909250565b6000546001600160a01b03163314806120b75750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6121035760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b6001600160a01b03166000908152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600554600d5461215c91906151ad565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156121d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121fd9190615212565b6115dd91906151ad565b60028054036122585760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556024546301000000900460ff16156122b65760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b602454640100000000900460ff16156123115760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b61231d33336001613b9b565b5060008061232b3385613f9b565b91509150600083836040015161234191906151ff565b905060035461235b906001600160a01b0316333087614128565b600354600480546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0391821692810192909252602482018790529091169063095ea7b3906044016020604051808303816000875af11580156123cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f191906153d9565b50600480546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081529182018690526001600160a01b03169063a694fc3a906024016020604051808303816000875af1158015612454573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247891906153d9565b506040805160a0810182528681526020858101518183015281830184905260608087015190830152608080870151908301523360009081526027909152919091208054849081106124cb576124cb61513c565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505061251a3385600161429f565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6000806000806000602860009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156125bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e09190615410565b945094505093509350600083121580156125f957508115155b801561261d57508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b6126695760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610ba6565b50909392505050565b606060028054036126c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556126d533836001613b9b565b600160025592915050565b6001600160a01b0381166000908152600f602052604081205460ff1615612705575090565b506001600160a01b039081166000908152602360205260409020541690565b919050565b600280540361277a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ba6565b600280556024546301000000900460ff16156127d85760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b602454640100000000900460ff16156128335760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b61283f33336001613b9b565b5060008061284d3385613f9b565b915091504283116128a05760405162461bcd60e51b815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610ba6565b6000428360600151116128b45760006128c4565b4283606001516128c4919061519a565b905060006128d2428661519a565b90508181116129235760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610ba6565b600a548110156129755760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ba6565b6009548111156129c75760405162461bcd60e51b815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ba6565b6040518060a00160405280878152602001428152602001856040015181526020018681526020016129f783610c24565b9052336000908152602760205260409020805485908110612a1a57612a1a61513c565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612a6a33600060016143c0565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b6001600160a01b0381166000908152602080526040812054600554670de0b6b3a764000091610f7b916151ad565b60005484906001600160a01b0316331480612b0e5750612b0e3382610f85565b612b5a5760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b6001600160a01b038516600090815260176020526040902054601580548692908110612b8857612b8861513c565b906000526020600020018190555082601360176000886001600160a01b03166001600160a01b031681526020019081526020016000205481548110612bcf57612bcf61513c565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055918716815260179091526040902054601480548492908110612c3357612c3361513c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050505050565b6001600160a01b0381166000908152600f602052604090205460ff16612cd05760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ba6565b6001600160a01b038116600090815260106020908152604080832033845290915290205460ff16612d435760405162461bcd60e51b815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610ba6565b336000908152602360205260409020546001600160a01b03168015612d9d5733600090815260208080526040808320546001600160a01b038516845260229092528220805491929091612d9790849061519a565b90915550505b33600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387169081179091558280528184205490845260229092528220805491929091612e059084906151ff565b90915550505050565b60005482906001600160a01b0316331480612e2e5750612e2e3382610f85565b612e7a5760405162461bcd60e51b815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ba6565b506001600160a01b03918216600090815260116020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6000546001600160a01b0316331480612eed5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612f395760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600f602052604090205460ff16612fca5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ba6565b3360008181526010602090815260408083206001600160a01b038681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603613095576001600160a01b038116600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055818052808320543384526022909252822080549192909161308f90849061519a565b90915550505b50565b600080601383815481106130ae576130ae61513c565b6000918252602090912001546001600160a01b03169050801561316f57670de0b6b3a7640000601c84815481106130e7576130e761513c565b9060005260206000200154826001600160a01b0316630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613130573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131549190615212565b61315e91906151ad565b61316891906151c4565b9150610b51565b601583815481106131825761318261513c565b9060005260206000200154915050919050565b60005b601354811015613336576000601382815481106131b7576131b761513c565b6000918252602090912001546001600160a01b03169050801561332d5782806131fc5750601d82815481106131ee576131ee61513c565b906000526020600020015442115b1561332d576040517f6472eee10000000000000000000000000000000000000000000000000000000081523060048201524260248201526001600160a01b03821690636472eee1906044016020604051808303816000875af1158015613266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061328a9190615212565b601c838154811061329d5761329d61513c565b9060005260206000200181905550806001600160a01b031663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330d9190615212565b601d83815481106133205761332061513c565b6000918252602090912001555b50600101613198565b5050565b6000546001600160a01b03163314806133665750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6133b25760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ba6565b8051670de0b6b3a7640000111561340b5760405162461bcd60e51b815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610ba6565b6080810151600111801590613425575060a0810151600111155b6134715760405162461bcd60e51b815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610ba6565b80516008556020810151600c556040810151600d556060810151600b55608081015160095560a00151600a55565b602454640100000000900460ff16156134fa5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b6135046000613195565b61350c6115f4565b6005556006544210613522576135206144fe565b565b613520614b99565b602454600090640100000000900460ff1661354d5761354b85856001613b9b565b505b60008061355a8786613f9b565b91509150816060015142101580613578575060245460ff1615156001145b6135c45760405162461bcd60e51b815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610ba6565b6040820151801561372657600480546040517f38d07436000000000000000000000000000000000000000000000000000000008152918201839052600060248301526001600160a01b0316906338d07436906044016020604051808303816000875af1158015613638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365c91906153d9565b50600354613674906001600160a01b03168883613e52565b6001600160a01b038816600090815260276020526040902080548390811061369e5761369e61513c565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556136d8908990839061429f565b60408051828152602081018890526001600160a01b03898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b60008183106137405781613742565b825b9392505050565b600085600161375a828260006143c0565b602454640100000000900460ff16156137b55760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b6024546301000000900460ff161561380f5760405162461bcd60e51b815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610ba6565b600a548510156138615760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ba6565b6009548511156138b35760405162461bcd60e51b815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ba6565b6003546138cb906001600160a01b0316883089614128565b600354600480546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0391821692810192909252602482018990529091169063095ea7b3906044016020604051808303816000875af115801561393d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396191906153d9565b50600480546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081529182018890526001600160a01b03169063a694fc3a906024016020604051808303816000875af11580156139c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139e891906153d9565b5060006139f486610c24565b6001600160a01b038a166000908152602080805260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206001600160a01b038e1660009081526027835283902060a0850184528185529184018a90529183018b90529092509060608101613acb8a8a6151ff565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613b27908b908a9061429f565b60408051898152602081018990529081018290526001600160a01b038a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b6000613b9642600654613731565b905090565b6060836001613bac828260006143c0565b602454640100000000900460ff1615613c075760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610ba6565b60245462010000900460ff1615613c605760405162461bcd60e51b815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ba6565b6001600160a01b0386166000908152601b6020526040902042905560125467ffffffffffffffff811115613c9657613c96615040565b604051908082528060200260200182016040528015613cbf578160200160208202803683370190505b50925060005b601254811015613e48576001600160a01b0387166000908152601a602090815260408083208484529091529020548451859083908110613d0757613d0761513c565b6020908102919091018101919091526001600160a01b0388166000908152601a825260408082208483529092529081208190558451859083908110613d4e57613d4e61513c565b60200260200101511115613e4057613db060128281548110613d7257613d7261513c565b9060005260206000200160009054906101000a90046001600160a01b031687868481518110613da357613da361513c565b6020026020010151613e52565b866001600160a01b03167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613ded57613ded61513c565b602002602001015160128481548110613e0857613e0861513c565b60009182526020918290200154604080519384526001600160a01b03918216928401929092528a169082015260600160405180910390a25b600101613cc5565b5050509392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613edc9190615460565b6000604051808303816000865af19150503d8060008114613f19576040519150601f19603f3d011682016040523d82523d6000602084013e613f1e565b606091505b5091509150818015613f48575080511580613f48575080806020019051810190613f4891906153d9565b613f945760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610ba6565b5050505050565b613fd06040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156140c65760005b6001600160a01b0385166000908152602760205260409020548110156140c4576001600160a01b03851660009081526027602052604090208054829081106140255761402561513c565b90600052602060002090600502016000015484036140bc576001600160a01b03851660009081526027602052604090208054829081106140675761406761513c565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506140c4565b600101613fdb565b505b82158015906140d55750815183145b6141215760405162461bcd60e51b815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610ba6565b9250929050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916141ba9190615460565b6000604051808303816000865af19150503d80600081146141f7576040519150601f19603f3d011682016040523d82523d6000602084013e6141fc565b606091505b509150915081801561422657508051158061422657508080602001905181019061422691906153d9565b6142975760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610ba6565b505050505050565b60006142aa846126e0565b905081156143375782601e60008282546142c491906151ff565b90915550506001600160a01b0384166000908152602080526040812080548592906142f09084906151ff565b90915550506001600160a01b03811615614332576001600160a01b0381166000908152602260205260408120805485929061432c9084906151ff565b90915550505b6143b7565b82601e6000828254614349919061519a565b90915550506001600160a01b03841660009081526020805260408120805485929061437590849061519a565b90915550506001600160a01b038116156143b7576001600160a01b038116600090815260226020526040812080548592906143b190849061519a565b90915550505b61142184600060015b602454640100000000900460ff166143e05781156143e0576143e061349f565b8015614409576143ef8361102a565b6001600160a01b0384166000908152600e60205260409020555b6001600160a01b03831615611eb557600080600061442686611eba565b6024549295509093509150640100000000900460ff166144495761444986614c02565b6001600160a01b0386166000908152600e602052604090208290558281106144b3576000614477848361519a565b905080601f5461448791906151ff565b601f5561449481856151ff565b6001600160a01b03881660009081526021602052604090205550614297565b60006144bf828561519a565b905080601f546144cf919061519a565b601f556144dc818561519a565b6001600160a01b03881660009081526021602052604090205550505050505050565b614506614b99565b60005b6014548110156145d3576000601482815481106145285761452861513c565b6000918252602090912001546001600160a01b0316905080156145ca576040517f092193ab0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063092193ab9060240160408051808303816000875af11580156145a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c7919061547c565b50505b50600101614509565b50600062093a80600654426145e8919061519a565b6145f291906151c4565b905060005b6012548110156147a457601281815481106146145761461461513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561467e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146a29190615212565b6146ad8360016151ff565b62093a806146ba84613098565b6146c491906151ad565b6146ce91906151ad565b1115601282815481106146e3576146e361513c565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660448201526058016040516020818303038152906040529061479b5760405162461bcd60e51b8152600401610ba69190614f30565b506001016145f7565b5062093a806147b48260016151ff565b6147be91906151ad565b6006546147cb91906151ff565b6006556015805460019081106147e3576147e361513c565b9060005260206000200154600014614b95576000601260018154811061480b5761480b61513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614875573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148999190615212565b9050600060126002815481106148b1576148b161513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561491b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061493f9190615212565b600480546040517f7050ccd90000000000000000000000000000000000000000000000000000000081523092810192909252600160248301529192506001600160a01b0390911690637050ccd9906044016020604051808303816000875af11580156149af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149d391906153d9565b50600060126001815481106149ea576149ea61513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614a54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a789190615212565b905060006012600281548110614a9057614a9061513c565b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015614afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1e9190615212565b905062093a80614b2e858461519a565b614b3891906151c4565b6015600181548110614b4c57614b4c61513c565b60009182526020909120015562093a80614b66848361519a565b614b7091906151c4565b6015600281548110614b8457614b8461513c565b600091825260209091200155505050505b6130955b6000614ba36117ee565b905060005b601854811015614bf357818181518110614bc457614bc461513c565b602002602001015160188281548110614bdf57614bdf61513c565b600091825260209091200155600101614ba8565b50614bfc613b88565b60075550565b6001600160a01b03811615613095576000614c1c82610a09565b905060005b8151811015614c7357818181518110614c3c57614c3c61513c565b6020908102919091018101516001600160a01b0385166000908152601a835260408082208583529093529190912055600101614c21565b5060005b8151811015611eb55760188181548110614c9357614c9361513c565b60009182526020808320909101546001600160a01b0386168352601982526040808420858552909252912055600101614c77565b6001600160a01b038116811461309557600080fd5b600060208284031215614cee57600080fd5b813561374281614cc7565b6020808252825182820181905260009190848201906040850190845b81811015614d3157835183529284019291840191600101614d15565b50909695505050505050565b801515811461309557600080fd5b600080600060608486031215614d6057600080fd5b833592506020840135614d7281614cc7565b91506040840135614d8281614d3d565b809150509250925092565b600060208284031215614d9f57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d315783516001600160a01b031683529284019291840191600101614dc2565b60008060408385031215614dfa57600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e6a5781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614e26565b5091979650505050505050565b60008060408385031215614e8a57600080fd5b8235614e9581614cc7565b91506020830135614ea581614cc7565b809150509250929050565b60008060008060808587031215614ec657600080fd5b8435614ed181614d3d565b93506020850135614ee181614d3d565b92506040850135614ef181614d3d565b91506060850135614f0181614d3d565b939692955090935050565b60005b83811015614f27578181015183820152602001614f0f565b50506000910152565b6020815260008251806020840152614f4f816040850160208701614f0c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614f9457600080fd5b8235614f9f81614cc7565b946020939093013593505050565b60008060408385031215614fc057600080fd5b8235614fcb81614cc7565b91506020830135614ea581614d3d565b60008060008060808587031215614ff157600080fd5b8435614ffc81614cc7565b935060208501359250604085013561501381614cc7565b91506060850135614f0181614cc7565b60006020828403121561503557600080fd5b813561374281614d3d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156150b6576150b6615040565b604052919050565b600060c082840312156150d057600080fd5b82601f8301126150df57600080fd5b60405160c0810181811067ffffffffffffffff8211171561510257615102615040565b6040528060c084018581111561511757600080fd5b845b81811015615131578035835260209283019201615119565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610c4a57610c4a61516b565b8082028115828204841417610c4a57610c4a61516b565b6000826151fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610c4a57610c4a61516b565b60006020828403121561522457600080fd5b5051919050565b600181811c9082168061523f57607f821691505b602082108103610b51577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600067ffffffffffffffff82111561529257615292615040565b5060051b60200190565b600082601f8301126152ad57600080fd5b815160206152c26152bd83615278565b61506f565b8083825260208201915060208460051b8701019350868411156152e457600080fd5b602086015b8481101561530057805183529183019183016152e9565b509695505050505050565b60008060006060848603121561532057600080fd5b835167ffffffffffffffff8082111561533857600080fd5b818601915086601f83011261534c57600080fd5b8151602061535c6152bd83615278565b82815260059290921b8401810191818101908a84111561537b57600080fd5b948201945b838610156153a257855161539381614cc7565b82529482019490820190615380565b918901519197509093505050808211156153bb57600080fd5b506153c88682870161529c565b925050604084015190509250925092565b6000602082840312156153eb57600080fd5b815161374281614d3d565b805169ffffffffffffffffffff8116811461272457600080fd5b600080600080600060a0868803121561542857600080fd5b615431866153f6565b9450602086015193506040860151925060608601519150615454608087016153f6565b90509295509295909350565b60008251615472818460208701614f0c565b9190910192915050565b6000806040838503121561548f57600080fd5b50508051602090910151909290915056fea26469706673582212203224042895f099e06381ae413bdb9836d4967292f17612d7df8e1595a897805a64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000004a4ef6be54d2666a6d56cf861de7ab3d150a20b600000000000000000000000000000000000000000000000000000000000000030000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0000000000000000000000000c0c293ce456ff0ed870add98a0828dd4d2903dbf000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000002e90edd00000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF,0xba100000625a3754423978a60c9317c58a424e3D
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [3] : _rewardRates (uint256[]): 115740740740,100000000000,200000000000
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [6] : _stakingToken (address): 0x4a4eF6Be54d2666A6D56cf861de7AB3D150a20b6
-----Encoded View---------------
27 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [5] : 00000000000000000000000000000000000000000000000000000000000002e0
Arg [6] : 0000000000000000000000004a4ef6be54d2666a6d56cf861de7ab3d150a20b6
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 000000000000000000000000c0c293ce456ff0ed870add98a0828dd4d2903dbf
Arg [10] : 000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [12] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [16] : 0000000000000000000000000000000000000000000000000000001af2af8c84
Arg [17] : 000000000000000000000000000000000000000000000000000000174876e800
Arg [18] : 0000000000000000000000000000000000000000000000000000002e90edd000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [24] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
107053:4359:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41878:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94441:316;;;;;;:::i;:::-;;:::i;:::-;;;1786:25:1;;;1774:2;1759:18;94441:316:0;1640:177:1;44776:222:0;;;;;;:::i;:::-;;:::i;39880:109::-;;;:::i;:::-;;;;;;;:::i;24816:141::-;;;;;;:::i;:::-;;:::i;:::-;;92020:190;;;;;;:::i;:::-;;:::i;42586:339::-;;;:::i;85802:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;45608:179::-;;;;;;:::i;:::-;;:::i;39292:459::-;;;;;;:::i;:::-;;:::i;:::-;;;4702:14:1;;4695:22;4677:41;;4665:2;4650:18;39292:459:0;4537:187:1;32000:107:0;;;;;-1:-1:-1;;;;;32000:107:0;;;;;;-1:-1:-1;;;;;4919:55:1;;;4901:74;;4889:2;4874:18;32000:107:0;4729:252:1;35738:60:0;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;35738:60:0;;;48135:1752;;;;;;:::i;:::-;;:::i;65107:572::-;;;;;;:::i;:::-;;:::i;43987:127::-;;;;;;:::i;:::-;-1:-1:-1;;;;;44080:26:0;44053:7;44080:26;;;:17;:26;;;;;;;43987:127;34574:48;;34616:6;34574:48;;54796:309;;;;;;:::i;:::-;;:::i;34163:49::-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;34163:49:0;;;107491:46;;;:::i;:::-;;;;;;;:::i;46770:181::-;;;;;;:::i;:::-;;:::i;24584:29::-;;;;;-1:-1:-1;;;;;24584:29:0;;;36571:31;;;:::i;109856:1553::-;;;:::i;43595:111::-;43676:22;;43595:111;;107294:47;;;;;-1:-1:-1;;;;;107294:47:0;;;34484:55;;;;;;:::i;:::-;;;;;;;;;;;;;;34966:54;;;;;;:::i;:::-;;;;;;;;;;;;;;33366:32;;;;;;40885:681;;;:::i;31961:32::-;;;;;-1:-1:-1;;;;;31961:32:0;;;80993:2692;;;;;;:::i;:::-;;:::i;56053:206::-;;;;;;:::i;:::-;;:::i;75505:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;8063:25:1;;;8119:2;8104:18;;8097:34;;;;8147:18;;;8140:34;;;;8205:2;8190:18;;8183:34;8248:3;8233:19;;8226:35;8050:3;8035:19;75505:53:0;7804:463:1;24965:271:0;;;:::i;35533:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;47147:199;;;;;;:::i;:::-;;:::i;66475:1087::-;;;;;;:::i;:::-;;:::i;36511:34::-;;;;;;;;;;;;83746:1961;;;;;;:::i;:::-;;:::i;:::-;;;;8474:25:1;;;8530:2;8515:18;;8508:34;;;;8558:18;;;8551:34;8462:2;8447:18;83746:1961:0;8272:319:1;24557:20:0;;;;;-1:-1:-1;;;;;24557:20:0;;;66079:161;;;;;;:::i;:::-;;:::i;35860:26::-;;;;;;;;;46064:224;;;;;;:::i;:::-;;:::i;33487:55::-;;;;;;88643:1540;;;;;;:::i;:::-;;:::i;33211:62::-;;;;;;109236:347;;;:::i;55591:172::-;;;;;;:::i;:::-;;:::i;47499:444::-;;;;;;:::i;:::-;;:::i;33057:29::-;;;;;;107348:39;;;;;-1:-1:-1;;;;;107348:39:0;;;86011:133;;;;;;:::i;:::-;-1:-1:-1;;;;;86108:21:0;86081:7;86108:21;;;:12;:21;;;;;:28;;86011:133;33137:50;;;;;;32730:30;;;;;;90237:1648;;;;;;:::i;:::-;;:::i;45233:166::-;;;;;;:::i;:::-;;:::i;69537:483::-;;;;;;:::i;:::-;;:::i;50907:800::-;;;;;;:::i;:::-;;:::i;43353:128::-;;;;;;:::i;:::-;-1:-1:-1;;;;;43447:26:0;43420:7;43447:26;;;:17;:26;;;;;;;43353:128;70340:207;;;;;;:::i;:::-;;:::i;43088:113::-;43170:23;;43088:113;;65843:97;;;:::i;50141:610::-;;;;;;:::i;:::-;;:::i;32950:27::-;;;;;;33625:51;;;;;;33701:59;;;;;;40363:452;;;;;;:::i;:::-;;:::i;63168:761::-;;;;;;:::i;:::-;;:::i;68025:958::-;;;;;;:::i;:::-;;:::i;64028:482::-;;;:::i;41878:529::-;41932:27;41972;42002:17;:15;:17::i;:::-;42057:12;:19;41972:47;;-1:-1:-1;42043:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42043:34:0;-1:-1:-1;;;;;;42094:26:0;;42123:1;42094:26;;;:17;:26;;;;;;42030:47;;-1:-1:-1;42094:30:0;42090:310;;42145:9;42140:249;42164:12;:19;42160:23;;42140:249;;;-1:-1:-1;;;;;42354:16:0;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;42273:32;;;:23;:32;;;;;:35;;;;;;;;;42257:13;;42313:4;;42273:35;42257:10;;42371:1;;42257:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;-1:-1:-1;;;;;42227:26:0;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;42226:91;;;;:::i;:::-;42225:148;;;;:::i;:::-;42209:10;42220:1;42209:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;42185:3;;42140:249;;;;42090:310;41961:446;41878:529;;;:::o;94441:316::-;94572:7;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;;;;;;;;;28833:1;29572:18;;94600:17:::1;::::0;::::1;::::0;::::1;;;:26;94592:57;;;::::0;-1:-1:-1;;;94592:57:0;;13081:2:1;94592:57:0::1;::::0;::::1;13063:21:1::0;13120:2;13100:18;;;13093:30;13159:20;13139:18;;;13132:48;13197:18;;94592:57:0::1;12879:342:1::0;94592:57:0::1;94667:82;94683:10;94695:19;94716:6;94724:24;94667:15;:82::i;:::-;28789:1:::0;29751:7;:22;94660:89;94441:316;-1:-1:-1;;;;94441:316:0:o;44776:222::-;44885:19;;44950:28;;44835:7;;44862:127;;44920:26;44885:19;44920:4;:26;:::i;:::-;44919:59;;;;:::i;:::-;44862:8;:127::i;:::-;44855:134;44776:222;-1:-1:-1;;44776:222:0:o;39880:109::-;39933:16;39969:12;39962:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39962:19:0;;;;;;;;;;;;;;;;;;;;;;;39880:109;:::o;24816:141::-;25296:5;;-1:-1:-1;;;;;25296:5:0;25282:10;:19;25274:79;;;;-1:-1:-1;;;25274:79:0;;13428:2:1;25274:79:0;;;13410:21:1;13467:2;13447:18;;;13440:30;13506:34;13486:18;;;13479:62;13577:17;13557:18;;;13550:45;13612:19;;25274:79:0;13226:411:1;25274:79:0;24888:14:::1;:23:::0;;;::::1;-1:-1:-1::0;;;;;24888:23:0;::::1;::::0;;::::1;::::0;;;24927:22:::1;::::0;4901:74:1;;;24927:22:0::1;::::0;4889:2:1;4874:18;24927:22:0::1;;;;;;;24816:141:::0;:::o;92020:190::-;92105:7;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;92132:70:::1;92145:10;::::0;92169:9;92180:4;92186:15:::1;92132:12;:70::i;:::-;28789:1:::0;29751:7;:22;92125:77;92020:190;-1:-1:-1;;;92020:190:0:o;42586:339::-;42736:17;:24;42641:41;;42722:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42722:39:0;;42695:66;;42779:9;42774:144;42798:17;:24;42794:28;;42774:144;;;34616:6;42874:14;42886:1;42874:11;:14::i;:::-;:32;;;;:::i;:::-;42844:24;42869:1;42844:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;42824:3;;42774:144;;;;42586:339;:::o;85802:133::-;-1:-1:-1;;;;;85906:21:0;;;;;;:12;:21;;;;;;;;85899:28;;;;;;;;;;;;;;;;;85866:20;;85899:28;;85906:21;;85899:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85802:133;;;:::o;45608:179::-;-1:-1:-1;;;;;45723:32:0;;45677:7;45723:32;;;:17;:32;;;;;;45705:15;;32858:4;;45705:50;;;:::i;:::-;45704:75;;;;:::i;39292:459::-;-1:-1:-1;;;;;39409:32:0;;39388:4;39409:32;;;:13;:32;;;;;;;;39404:297;;-1:-1:-1;39450:5:0;39443:12;;39404:297;-1:-1:-1;;;;;39475:25:0;;;;:60;;-1:-1:-1;;;;;;39504:31:0;;;39475:60;39471:230;;;-1:-1:-1;39544:5:0;39537:12;;39471:230;39584:5;;-1:-1:-1;;;;;39584:5:0;;;39569:20;;;;39565:136;;-1:-1:-1;39598:4:0;39591:11;;39565:136;-1:-1:-1;;;;;39640:33:0;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;39636:65;;-1:-1:-1;39697:4:0;39690:11;;39636:65;-1:-1:-1;39737:5:0;39292:459;;;;:::o;48135:1752::-;48198:24;;;48359:20;48371:7;48359:11;:20::i;:::-;48339:40;-1:-1:-1;;;;;;48410:23:0;;;48409:81;;48464:26;;;;;-1:-1:-1;;;;;4919:55:1;;48464:26:0;;;4901:74:1;32465:42:0;;48464:15;;4874:18:1;;48464:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48409:81;;;48437:24;;;;;-1:-1:-1;;;;;4919:55:1;;48437:24:0;;;4901:74:1;32465:42:0;;48437:15;;4874:18:1;;48437:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48390:100;;48596:19;32858:4;32465:42;-1:-1:-1;;;;;48720:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;48661:24;;48638:20;;48619:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;48618:145;;;;:::i;:::-;48596:167;-1:-1:-1;48872:19:0;;-1:-1:-1;;;;;49087:23:0;;;49086:94;;49145:35;49170:9;49145:24;:35::i;:::-;49086:94;;;49114:28;49134:7;49114:19;:28::i;:::-;49057:123;-1:-1:-1;49201:30:0;;49197:323;;49252:27;49326:26;49283:39;32858:4;49283:16;:39;:::i;:::-;49282:70;;;;:::i;:::-;49252:100;;32858:4;49426:20;;49404:19;:42;;;;:::i;:::-;49403:67;;;;:::i;:::-;49389:81;;49232:254;49197:323;;;49519:1;49505:15;;49197:323;48902:699;49688:11;49674;:25;:53;;49716:11;49674:53;;;49702:11;49674:53;49654:74;;49818:20;;49799:16;:39;49795:84;;;49859:20;;49840:39;;49795:84;48224:1663;;;;48135:1752;;;:::o;65107:572::-;36781:5;;-1:-1:-1;;;;;36781:5:0;36767:10;:19;;:79;;-1:-1:-1;36804:42:0;36790:10;:56;36767:79;36759:113;;;;-1:-1:-1;;;36759:113:0;;14033:2:1;36759:113:0;;;14015:21:1;14072:2;14052:18;;;14045:30;14111:23;14091:18;;;14084:51;14152:18;;36759:113:0;13831:345:1;36759:113:0;65309:13:::1;:30:::0;;65350:38;;65309:30;;::::1;;;65350:38:::0;;;65309:30:::1;65350:38:::0;::::1;;;;65399:50:::0;::::1;::::0;;::::1;;;;::::0;;65590:23;:50;::::1;;;-1:-1:-1::0;65618:22:0::1;::::0;;;::::1;;;65617:23;65590:50;65587:84;;;65642:22;:29:::0;;;::::1;::::0;::::1;::::0;;65587:84:::1;65107:572:::0;;;;:::o;54796:309::-;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;54894:22:::1;::::0;;;::::1;;;54893:23;54885:60;;;::::0;-1:-1:-1;;;54885:60:0;;14383:2:1;54885:60:0::1;::::0;::::1;14365:21:1::0;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;54885:60:0::1;14181:348:1::0;54885:60:0::1;54964:23;::::0;;;::::1;;;:32;54956:70;;;::::0;-1:-1:-1;;;54956:70:0;;14736:2:1;54956:70:0::1;::::0;::::1;14718:21:1::0;14775:2;14755:18;;;14748:30;14814:27;14794:18;;;14787:55;14859:18;;54956:70:0::1;14534:349:1::0;54956:70:0::1;-1:-1:-1::0;28789:1:0;29751:7;:22;54796:309::o;107491:46::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;46770:181::-;46837:7;32858:4;46891:28;;46865:23;46880:7;46865:14;:23::i;:::-;:54;;;;:::i;36571:31::-;;;;;;;:::i;109856:1553::-;109912:25;110177:15;110195:18;;;;;;;;;-1:-1:-1;;;;;110195:18:0;-1:-1:-1;;;;;110195:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110336:17;;:40;;;;;;;;1786:25:1;;;110177:48:0;;-1:-1:-1;110305:25:0;;-1:-1:-1;;;;;110336:17:0;;;;:31;;1759:18:1;;110336:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110301:75;;;;110391:22;110416:8;110425:1;110416:11;;;;;;;;:::i;:::-;;;;;;;110391:36;;110442:28;110508:21;:19;:21::i;:::-;110483:47;;:14;:47;:::i;:::-;110473:58;;110474:4;110473:58;:::i;:::-;110442:89;;110712:18;;;;;;;;;-1:-1:-1;;;;;110712:18:0;-1:-1:-1;;;;;110712:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110687:61;;110688:20;110687:61;:::i;:::-;110667:81;;110130:630;;;;109856:1553;:::o;40885:681::-;40933:41;40991:23;;41018:1;40991:28;:59;;;-1:-1:-1;41023:22:0;;:27;40991:59;40987:572;;;41074:21;41067:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40885:681;:::o;40987:572::-;41178:12;:19;41164:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41164:34:0;;41137:61;;41218:9;41213:289;41237:21;:28;41233:32;;41213:289;;;41445:22;;41420:14;41432:1;41420:11;:14::i;:::-;41402;;41373:26;:24;:26::i;:::-;:43;;;;:::i;:::-;41372:62;;;;:::i;:::-;:69;;41437:4;41372:69;:::i;:::-;41371:96;;;;:::i;:::-;41321:21;41343:1;41321:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;41291:24;41316:1;41291:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;41267:3;;41213:289;;80993:2692;-1:-1:-1;;;;;81184:21:0;;81082:32;81184:21;;;:12;:21;;;;;:32;;81082;;81184:21;81206:9;;81184:32;;;;;;:::i;:::-;;;;;;;;;81153:63;;;;;;;;81184:32;;;;;;;81153:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;81399:28:0;;;;:19;:28;;;;;;81153:63;;-1:-1:-1;;81395:224:0;;;-1:-1:-1;81492:25:0;;;;81395:224;;;-1:-1:-1;;;;;;81579:28:0;;;;;;:19;:28;;;;;;81395:224;81708:15;81678:9;:26;;;:45;81674:1802;;81903:26;;;;-1:-1:-1;;;;;81872:28:0;;;;;;:19;:28;;;;;;:57;81868:1087;;;81949:26;82007:17;81978:9;:26;;;:46;;;;:::i;:::-;81949:75;;82043:25;82089:9;:26;;;82071:15;:44;;;;:::i;:::-;82043:72;-1:-1:-1;82195:33:0;82231:38;82246:22;82267:1;82246:18;:22;:::i;82231:38::-;82195:74;-1:-1:-1;82486:17:0;82558:21;82562:17;82486;82558:21;:::i;:::-;82507:46;82535:18;82507:25;:46;:::i;:::-;82506:74;;;;:::i;:::-;82486:94;-1:-1:-1;82639:38:0;82660:17;82639:18;:38;:::i;:::-;82626:52;;:9;:52;:::i;:::-;82599:79;;81930:764;;;;81674:1802;;81868:1087;82938:1;82911:28;;81674:1802;;;83100:21;83155:20;83207:17;83178:9;:26;;;:46;;;;:::i;:::-;83155:69;;83243:20;83295:15;83266:9;:26;;;:44;;;;:::i;:::-;83243:67;-1:-1:-1;83377:1:0;83346:27;83243:67;83346:12;:27;:::i;:::-;83345:33;;;;:::i;:::-;83329:49;;83136:258;;83435:29;83450:13;83435:14;:29::i;:::-;83408:56;;83020:456;81674:1802;83598:9;:25;;;83571:24;:52;83567:110;;;83652:9;:25;;;83625:52;;83567:110;81116:2569;;80993:2692;;;;:::o;56053:206::-;56155:16;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;56191:60:::1;56202:10;56214:19:::0;56235:15;56191:10:::1;:60::i;75505:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75505:53:0;;-1:-1:-1;75505:53:0;;;:::o;24965:271::-;25034:14;;-1:-1:-1;;;;;25034:14:0;25020:10;:28;25012:94;;;;-1:-1:-1;;;25012:94:0;;17854:2:1;25012:94:0;;;17836:21:1;17893:2;17873:18;;;17866:30;17932:34;17912:18;;;17905:62;18003:23;17983:18;;;17976:51;18044:19;;25012:94:0;17652:417:1;25012:94:0;25135:5;;;25142:14;25122:35;;;-1:-1:-1;;;;;25135:5:0;;;18309:34:1;;25142:14:0;;;;18374:2:1;18359:18;;18352:43;25122:35:0;;18221:18:1;25122:35:0;;;;;;;25176:14;;;;25168:22;;;;;;-1:-1:-1;;;;;25176:14:0;;25168:22;;;;25201:27;;;24965:271::o;47147:199::-;47225:7;32858:4;47286:28;;47253:30;47269:13;47253:15;:30::i;66475:1087::-;36984:5;;66561:12;;-1:-1:-1;;;;;36984:5:0;36970:10;:19;;:74;;;36993:51;37011:10;37023:20;36993:17;:51::i;:::-;36962:107;;;;-1:-1:-1;;;36962:107:0;;18608:2:1;36962:107:0;;;18590:21:1;18647:2;18627:18;;;18620:30;18686:22;18666:18;;;18659:50;18726:18;;36962:107:0;18406:344:1;36962:107:0;-1:-1:-1;;;;;66659:27:0;::::1;66643:13;66659:27:::0;;;:13:::1;:27;::::0;;;;;::::1;;::::0;66913:54;::::1;;;-1:-1:-1::0;;;;;;66925:28:0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;66957:10;66925:42;66913:54;66912:113;;;;66991:8;66990:9;:34;;;;-1:-1:-1::0;67018:5:0::1;::::0;-1:-1:-1;;;;;67018:5:0::1;67004:10;:19;66990:34;66890:665;;;67246:12;::::0;-1:-1:-1;;;;;67246:12:0;;::::1;67222:37:::0;;::::1;::::0;67218:90:::1;;67261:18;::::0;;:47:::1;::::0;;;;;;::::1;18923:25:1::0;;;67261:18:0::1;18964::1::0;;;18957:50;-1:-1:-1;;;;;67261:18:0::1;::::0;:27:::1;::::0;18896:18:1;;67261:47:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;67218:90;67325:66;67353:12;67367:10;67379:11;67325:27;:66::i;66890:665::-;67507:36;::::0;-1:-1:-1;;;67507:36:0;;19470:2:1;67507:36:0::1;::::0;::::1;19452:21:1::0;19509:2;19489:18;;;19482:30;19548:28;19528:18;;;19521:56;19594:18;;67507:36:0::1;19268:350:1::0;37080:1:0::1;66475:1087:::0;;;:::o;83746:1961::-;-1:-1:-1;;;;;84049:26:0;;83847:27;84049:26;;;:17;:26;;;;;;;83847:27;84236:24;84067:7;84236:15;:24::i;:::-;-1:-1:-1;;;;;84336:26:0;;84273:33;84336:26;;;:17;:26;;;;;;84213:47;;-1:-1:-1;84273:33:0;84336:31;:66;;;;-1:-1:-1;;;;;;84371:26:0;;;;;;:17;:26;;;;;;:31;84336:66;84335:143;;;-1:-1:-1;;;;;;84446:31:0;;;;;;:22;:31;;;;;;84422:55;;;84335:143;84317:638;;;-1:-1:-1;84719:20:0;84317:638;;;-1:-1:-1;;;;;84907:31:0;;;;;;:22;:31;;;;;;84942:1;;84884:54;;:20;:54;:::i;:::-;84883:60;;;;:::i;:::-;84855:88;;84317:638;85090:1;85068:23;;85107:9;85102:598;-1:-1:-1;;;;;85126:21:0;;;;;;:12;:21;;;;;:28;85122:32;;85102:598;;;-1:-1:-1;;;;;85207:21:0;;85176:28;85207:21;;;:12;:21;;;;;:24;;85229:1;;85207:24;;;;;;:::i;:::-;;;;;;;;;;;85176:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85303:32;85338:34;85361:7;85370:1;85338:22;:34::i;:::-;85454:19;;;;85303:69;;-1:-1:-1;85434:17:0;32858:4;85549:52;85576:25;85303:69;85549:52;:::i;:::-;85536:66;;:9;:66;:::i;:::-;85535:91;;;;:::i;:::-;85522:105;;:9;:105;:::i;:::-;85488:139;-1:-1:-1;85642:46:0;85488:139;85642:46;;:::i;:::-;;-1:-1:-1;;85156:3:0;;;;;-1:-1:-1;85102:598:0;;-1:-1:-1;;85102:598:0;;;83976:1731;83746:1961;;;;;:::o;66079:161::-;36781:5;;-1:-1:-1;;;;;36781:5:0;36767:10;:19;;:79;;-1:-1:-1;36804:42:0;36790:10;:56;36767:79;36759:113;;;;-1:-1:-1;;;36759:113:0;;14033:2:1;36759:113:0;;;14015:21:1;14072:2;14052:18;;;14045:30;14111:23;14091:18;;;14084:51;14152:18;;36759:113:0;13831:345:1;36759:113:0;-1:-1:-1;;;;;66200:32:0::1;;::::0;;;:19:::1;:32;::::0;;;;;;66164:68;;::::1;66200:32;::::0;;::::1;66199:33;66164:68;::::0;;66079:161::o;46064:224::-;46130:7;46264:15;;46233:28;;:46;;;;:::i;:::-;46158:24;;;;;-1:-1:-1;;;;;4919:55:1;;46158:24:0;;;4901:74:1;32858:4:0;;;;32465:42;;46158:15;;4874:18:1;;46158:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;88643:1540::-;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;88784:13:::1;::::0;;;::::1;;;88783:14;88775:41;;;::::0;-1:-1:-1;;;88775:41:0;;19825:2:1;88775:41:0::1;::::0;::::1;19807:21:1::0;19864:2;19844:18;;;19837:30;19903:16;19883:18;;;19876:44;19937:18;;88775:41:0::1;19623:338:1::0;88775:41:0::1;88884:22;::::0;;;::::1;;;88883:23;88875:60;;;::::0;-1:-1:-1;;;88875:60:0;;14383:2:1;88875:60:0::1;::::0;::::1;14365:21:1::0;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;88875:60:0::1;14181:348:1::0;88875:60:0::1;88999:40;89010:10;89022;89034:4;88999:10;:40::i;:::-;;89101:28;89131:21:::0;89156:29:::1;89166:10;89178:6;89156:9;:29::i;:::-;89100:85;;;;89235:15;89275:8;89253:9;:19;;;:30;;;;:::i;:::-;89235:48:::0;-1:-1:-1;89454:12:0::1;::::0;89414:91:::1;::::0;-1:-1:-1;;;;;89454:12:0::1;89469:10;89489:4;89496:8:::0;89414:31:::1;:91::i;:::-;89651:12;::::0;89680:18:::1;::::0;;89651:59:::1;::::0;;;;-1:-1:-1;;;;;89680:18:0;;::::1;89651:59:::0;;::::1;20485:74:1::0;;;;20575:18;;;20568:34;;;89651:12:0;;::::1;::::0;:20:::1;::::0;20458:18:1;;89651:59:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89721:18:0::1;::::0;;:34:::1;::::0;;;;;;::::1;1786:25:1::0;;;-1:-1:-1;;;;;89721:18:0::1;::::0;:24:::1;::::0;1759:18:1;;89721:34:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89839:186:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;89886:25:::0;;::::1;::::0;89839:186;;::::1;::::0;;;;;;;;89948:26;;::::1;::::0;89839:186;;;;;89989:25;;::::1;::::0;89839:186;;;;89810:10:::1;-1:-1:-1::0;89797:24:0;;;:12:::1;:24:::0;;;;;;;:39;;89822:13;;89797:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90069:42;90084:10;90096:8;90106:4;90069:14;:42::i;:::-;90129:46;::::0;;20787:25:1;;;20843:2;20828:18;;20821:34;;;90146:10:0::1;::::0;90129:46:::1;::::0;20760:18:1;90129:46:0::1;;;;;;;-1:-1:-1::0;;28789:1:0;29751:7;:22;-1:-1:-1;;;88643:1540:0:o;109236:347::-;109288:3;109331:14;109347:9;109360:17;109379:22;109405:15;;;;;;;;;-1:-1:-1;;;;;109405:15:0;-1:-1:-1;;;;;109405:31:0;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109330:108;;;;;;;;;109466:1;109457:5;:10;;:27;;;;-1:-1:-1;109471:13:0;;;109457:27;:57;;;;;109507:7;109488:26;;:15;:26;;;;109457:57;109449:93;;;;-1:-1:-1;;;109449:93:0;;21730:2:1;109449:93:0;;;21712:21:1;21769:2;21749:18;;;21742:30;21808:25;21788:18;;;21781:53;21851:18;;109449:93:0;21528:347:1;109449:93:0;-1:-1:-1;109570:5:0;;109236:347;-1:-1:-1;;;109236:347:0:o;55591:172::-;55670:16;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;55706:49:::1;55717:10;55729:19:::0;55750:4:::1;55706:10;:49::i;:::-;28789:1:::0;29751:7;:22;55699:56;55591:172;-1:-1:-1;;55591:172:0:o;47499:444::-;-1:-1:-1;;;;;47578:25:0;;47555:7;47578:25;;;:19;:25;;;;;;;;47574:362;;;-1:-1:-1;47781:4:0;47499:444::o;47574:362::-;-1:-1:-1;;;;;;47893:31:0;;;;;;;:25;:31;;;;;;;;47499:444::o;47574:362::-;47499:444;;;:::o;90237:1648::-;28833:1;29439:7;;:19;29431:63;;;;-1:-1:-1;;;29431:63:0;;12721:2:1;29431:63:0;;;12703:21:1;12760:2;12740:18;;;12733:30;12799:33;12779:18;;;12772:61;12850:18;;29431:63:0;12519:355:1;29431:63:0;28833:1;29572:18;;90379:13:::1;::::0;;;::::1;;;90378:14;90370:41;;;::::0;-1:-1:-1;;;90370:41:0;;19825:2:1;90370:41:0::1;::::0;::::1;19807:21:1::0;19864:2;19844:18;;;19837:30;19903:16;19883:18;;;19876:44;19937:18;;90370:41:0::1;19623:338:1::0;90370:41:0::1;90479:22;::::0;;;::::1;;;90478:23;90470:60;;;::::0;-1:-1:-1;;;90470:60:0;;14383:2:1;90470:60:0::1;::::0;::::1;14365:21:1::0;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;90470:60:0::1;14181:348:1::0;90470:60:0::1;90594:40;90605:10;90617;90629:4;90594:10;:40::i;:::-;;90696:28;90726:21:::0;90751:29:::1;90761:10;90773:6;90751:9;:29::i;:::-;90695:85;;;;90835:15;90819:13;:31;90811:65;;;::::0;-1:-1:-1;;;90811:65:0;;22082:2:1;90811:65:0::1;::::0;::::1;22064:21:1::0;22121:2;22101:18;;;22094:30;22160:23;22140:18;;;22133:51;22201:18;;90811:65:0::1;21880:345:1::0;90811:65:0::1;90922:17;90972:15;90943:9;:26;;;:44;90942:97;;91038:1;90942:97;;;91020:15;90991:9;:26;;;:44;;;;:::i;:::-;90922:117:::0;-1:-1:-1;91050:16:0::1;91069:31;91085:15;91069:13:::0;:31:::1;:::i;:::-;91050:50;;91206:9;91195:8;:20;91187:57;;;::::0;-1:-1:-1;;;91187:57:0;;22432:2:1;91187:57:0::1;::::0;::::1;22414:21:1::0;22471:2;22451:18;;;22444:30;22510:26;22490:18;;;22483:54;22554:18;;91187:57:0::1;22230:348:1::0;91187:57:0::1;91275:13;;91263:8;:25;;91255:64;;;::::0;-1:-1:-1;;;91255:64:0;;22785:2:1;91255:64:0::1;::::0;::::1;22767:21:1::0;22824:2;22804:18;;;22797:30;22863:28;22843:18;;;22836:56;22909:18;;91255:64:0::1;22583:350:1::0;91255:64:0::1;91350:28;;91338:8;:40;;91330:80;;;::::0;-1:-1:-1;;;91330:80:0;;23140:2:1;91330:80:0::1;::::0;::::1;23122:21:1::0;23179:2;23159:18;;;23152:30;23218:29;23198:18;;;23191:57;23265:18;;91330:80:0::1;22938:351:1::0;91330:80:0::1;91494:174;;;;;;;;91520:6;91494:174;;;;91541:15;91494:174;;;;91571:9;:19;;;91494:174;;;;91605:13;91494:174;;;;91633:24;91648:8;91633:14;:24::i;:::-;91494:174:::0;;91465:10:::1;91452:24;::::0;;;:12:::1;:24;::::0;;;;:39;;91477:13;;91452:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91737:48;91761:10;91773:5;91780:4;91737:23;:48::i;:::-;91803:74;::::0;;23525:25:1;;;23581:2;23566:18;;23559:34;;;91846:15:0::1;23609:18:1::0;;;23602:34;23667:2;23652:18;;23645:34;;;91803:74:0;;91816:10:::1;::::0;91803:74:::1;::::0;;;;;23512:3:1;91803:74:0;;::::1;-1:-1:-1::0;;28789:1:0;29751:7;:22;-1:-1:-1;;;;90237:1648:0:o;45233:166::-;-1:-1:-1;;;;;45341:26:0;;45295:7;45341:26;;;:17;:26;;;;;;45323:15;;32858:4;;45323:44;;;:::i;69537:483::-;36984:5;;69703:20;;-1:-1:-1;;;;;36984:5:0;36970:10;:19;;:74;;;36993:51;37011:10;37023:20;36993:17;:51::i;:::-;36962:107;;;;-1:-1:-1;;;36962:107:0;;18608:2:1;36962:107:0;;;18590:21:1;18647:2;18627:18;;;18620:30;18686:22;18666:18;;;18659:50;18726:18;;36962:107:0;18406:344:1;36962:107:0;-1:-1:-1;;;;;69754:42:0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;69736:17:::1;:61:::0;;69800:9;;69754:42;69736:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;69883:25;69820:16;69837:20;:42;69858:20;-1:-1:-1::0;;;;;69837:42:0::1;-1:-1:-1::0;;;;;69837:42:0::1;;;;;;;;;;;;;69820:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;-1:-1:-1::0;;;;;69820:88:0;;::::1;;::::0;;69938:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;69919:18:::1;:62:::0;;69984:28;;69938:42;69919:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;-1:-1:-1::0;;;;;69919:93:0::1;;;;;-1:-1:-1::0;;;;;69919:93:0::1;;;;;;69537:483:::0;;;;;:::o;50907:800::-;-1:-1:-1;;;;;50987:34:0;;;;;;:19;:34;;;;;;;;50979:60;;;;-1:-1:-1;;;50979:60:0;;23892:2:1;50979:60:0;;;23874:21:1;23931:2;23911:18;;;23904:30;23970:15;23950:18;;;23943:43;24003:18;;50979:60:0;23690:337:1;50979:60:0;-1:-1:-1;;;;;51058:36:0;;;;;;:21;:36;;;;;;;;51095:10;51058:48;;;;;;;;;;51050:90;;;;-1:-1:-1;;;51050:90:0;;24234:2:1;51050:90:0;;;24216:21:1;24273:2;24253:18;;;24246:30;24312:31;24292:18;;;24285:59;24361:18;;51050:90:0;24032:353:1;51050:90:0;51286:10;51235:22;51260:37;;;:25;:37;;;;;;-1:-1:-1;;;;;51260:37:0;51312:28;;51308:182;;51467:10;51449:29;;;;:17;:29;;;;;;;;-1:-1:-1;;;;;51412:33:0;;;;:17;:33;;;;;:66;;51449:29;;51412:33;;:66;;51449:29;;51412:66;:::i;:::-;;;;-1:-1:-1;;51308:182:0;51558:10;51532:37;;;;:25;:37;;;;;;;;:53;;;;-1:-1:-1;;;;;51532:53:0;;;;;;;;51670:29;;;;;;;51634:32;;;:17;:32;;;;;:65;;51670:29;;51634:32;;:65;;51670:29;;51634:65;:::i;:::-;;;;-1:-1:-1;;;;50907:800:0:o;70340:207::-;36984:5;;70448:20;;-1:-1:-1;;;;;36984:5:0;36970:10;:19;;:74;;;36993:51;37011:10;37023:20;36993:17;:51::i;:::-;36962:107;;;;-1:-1:-1;;;36962:107:0;;18608:2:1;36962:107:0;;;18590:21:1;18647:2;18627:18;;;18620:30;18686:22;18666:18;;;18659:50;18726:18;;36962:107:0;18406:344:1;36962:107:0;-1:-1:-1;;;;;;70481:36:0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;70340:207::o;65843:97::-;36781:5;;-1:-1:-1;;;;;36781:5:0;36767:10;:19;;:79;;-1:-1:-1;36804:42:0;36790:10;:56;36767:79;36759:113;;;;-1:-1:-1;;;36759:113:0;;14033:2:1;36759:113:0;;;14015:21:1;14072:2;14052:18;;;14045:30;14111:23;14091:18;;;14084:51;14152:18;;36759:113:0;13831:345:1;36759:113:0;65918:14:::1;::::0;;65900:32;;::::1;65918:14;::::0;;::::1;65917:15;65900:32;::::0;;65843:97::o;50141:610::-;50240:10;50220:31;;;;:19;:31;;;;;;;;50212:57;;;;-1:-1:-1;;;50212:57:0;;23892:2:1;50212:57:0;;;23874:21:1;23931:2;23911:18;;;23904:30;23970:15;23950:18;;;23943:43;24003:18;;50212:57:0;23690:337:1;50212:57:0;50355:10;50333:33;;;;:21;:33;;;;;;;;-1:-1:-1;;;;;50333:49:0;;;;;;;;;;;;;;;;50332:50;50280:102;;;;;;;50485:25;:41;;;;;;;;:55;50481:263;;-1:-1:-1;;;;;50556:41:0;;50608:1;50556:41;;;:25;:41;;;;;;;;:54;;;;;;50699:33;;;;;;;50684:10;50666:29;;:17;:29;;;;;:66;;50699:33;;50666:29;;:66;;50699:33;;50666:66;:::i;:::-;;;;-1:-1:-1;;50481:263:0;50141:610;:::o;40363:452::-;40424:16;40453:32;40488:16;40505:9;40488:27;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;40488:27:0;;-1:-1:-1;40530:38:0;;40526:282;;40711:4;40669:27;40697:9;40669:38;;;;;;;;:::i;:::-;;;;;;;;;40618:24;-1:-1:-1;;;;;40597:67:0;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;40596:119;;;;:::i;:::-;40585:130;;40526:282;;;40768:17;40786:9;40768:28;;;;;;;;:::i;:::-;;;;;;;;;40757:39;;40442:373;40363:452;;;:::o;63168:761::-;63285:9;63280:642;63304:16;:23;63300:27;;63280:642;;;63349:32;63384:16;63401:1;63384:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;63384:19:0;;-1:-1:-1;63422:38:0;;63418:493;;63485:12;:61;;;;63520:22;63543:1;63520:25;;;;;;;;:::i;:::-;;;;;;;;;63502:15;:43;63485:61;63481:415;;;63660:106;;;;;63743:4;63660:106;;;20485:74:1;63750:15:0;20575:18:1;;;20568:34;-1:-1:-1;;;;;63660:74:0;;;;;20458:18:1;;63660:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63627:27;63655:1;63627:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;63838:24;-1:-1:-1;;;;;63817:57:0;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63789:22;63812:1;63789:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;63481:415;-1:-1:-1;63329:3:0;;63280:642;;;;63168:761;:::o;68025:958::-;36781:5;;-1:-1:-1;;;;;36781:5:0;36767:10;:19;;:79;;-1:-1:-1;36804:42:0;36790:10;:56;36767:79;36759:113;;;;-1:-1:-1;;;36759:113:0;;14033:2:1;36759:113:0;;;14015:21:1;14072:2;14052:18;;;14045:30;14111:23;14091:18;;;14084:51;14152:18;;36759:113:0;13831:345:1;36759:113:0;68434:13;;32858:4:::1;-1:-1:-1::0;68434:37:0::1;68426:69;;;::::0;-1:-1:-1;;;68426:69:0;;24592:2:1;68426:69:0::1;::::0;::::1;24574:21:1::0;24631:2;24611:18;;;24604:30;24670:21;24650:18;;;24643:49;24709:18;;68426:69:0::1;24390:343:1::0;68426:69:0::1;68619:13:::0;;::::1;::::0;68636:1:::1;-1:-1:-1::0;68619:18:0;::::1;::::0;68618:44:::1;;-1:-1:-1::0;68643:13:0;;::::1;::::0;68660:1:::1;-1:-1:-1::0;68643:18:0::1;68618:44;68610:69;;;::::0;-1:-1:-1;;;68610:69:0;;25281:2:1;68610:69:0::1;::::0;::::1;25263:21:1::0;25320:2;25300:18;;;25293:30;25359:14;25339:18;;;25332:42;25391:18;;68610:69:0::1;25079:336:1::0;68610:69:0::1;68714:13:::0;;68692:19:::1;:35:::0;68714:13:::1;68761::::0;::::1;::::0;68738:20:::1;:36:::0;68816:13;;::::1;::::0;68785:28:::1;:44:::0;68867:13;;::::1;::::0;68840:24:::1;:40:::0;68922:13;;::::1;::::0;68891:28:::1;:44:::0;68962:13;::::1;::::0;68946::::1;:29:::0;68025:958::o;64028:482::-;64117:22;;;;;;;64116:23;64108:60;;;;-1:-1:-1;;;64108:60:0;;14383:2:1;64108:60:0;;;14365:21:1;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;64108:60:0;14181:348:1;64108:60:0;64230:25;64249:5;64230:18;:25::i;:::-;64325:16;:14;:16::i;:::-;64307:15;:34;64377:12;;64358:15;:31;64354:149;;64406:14;:12;:14::i;:::-;64028:482::o;64354:149::-;64462:29;:27;:29::i;95268:1780::-;95730:22;;95454:7;;95730:22;;;;;95726:194;;95855:53;95866:14;95882:19;95903:4;95855:10;:53::i;:::-;;95726:194;95973:28;96003:21;96028:33;96038:14;96054:6;96028:9;:33::i;:::-;95972:89;;;;96099:9;:26;;;96080:15;:45;;:71;;;-1:-1:-1;96129:14:0;;;;:22;;:14;:22;96080:71;96072:106;;;;-1:-1:-1;;;96072:106:0;;25622:2:1;96072:106:0;;;25604:21:1;25661:2;25641:18;;;25634:30;25700:24;25680:18;;;25673:52;25742:18;;96072:106:0;25420:346:1;96072:106:0;96209:19;;;;96245:13;;96241:771;;96437:18;;;:45;;;;;;;;18923:25:1;;;96437:18:0;18964::1;;;18957:50;-1:-1:-1;;;;;96437:18:0;;:27;;18896:18:1;;96437:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;96647:12:0;;96611:82;;-1:-1:-1;;;;;96647:12:0;96662:19;96683:9;96611:27;:82::i;:::-;-1:-1:-1;;;;;96765:28:0;;;;;;:12;:28;;;;;:43;;96794:13;;96765:43;;;;;;:::i;:::-;;;;;;;;;;;;;96758:50;;;;;;;;;;;;;;;;;;;;;;;;;;96860:48;;96875:14;;96891:9;;96860:14;:48::i;:::-;96930:70;;;25973:25:1;;;26029:2;26014:18;;26007:34;;;-1:-1:-1;;;;;26077:55:1;;;26057:18;;;26050:83;96930:70:0;;;;;;;;;;;25961:2:1;96930:70:0;;;96241:771;97031:9;95268:1780;-1:-1:-1;;;;;;;95268:1780: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;92406:1673::-;92652:7;92621:14;92637:4;37175:49;37199:7;37208:8;37218:5;37175:23;:49::i;:::-;92681:22:::1;::::0;;;::::1;;;92680:23;92672:60;;;::::0;-1:-1:-1;;;92672:60:0;;14383:2:1;92672:60:0::1;::::0;::::1;14365:21:1::0;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;92672:60:0::1;14181:348:1::0;92672:60:0::1;92752:13;::::0;;;::::1;;;92751:14;92743:41;;;::::0;-1:-1:-1;;;92743:41:0;;19825:2:1;92743:41:0::1;::::0;::::1;19807:21:1::0;19864:2;19844:18;;;19837:30;19903:16;19883:18;;;19876:44;19937:18;;92743:41:0::1;19623:338:1::0;92743:41:0::1;92811:13;;92803:4;:21;;92795:60;;;::::0;-1:-1:-1;;;92795:60:0;;22785:2:1;92795:60:0::1;::::0;::::1;22767:21:1::0;22824:2;22804:18;;;22797:30;22863:28;22843:18;;;22836:56;22909:18;;92795:60:0::1;22583:350:1::0;92795:60:0::1;92882:28;;92874:4;:36;;92866:75;;;::::0;-1:-1:-1;;;92866:75:0;;23140:2:1;92866:75:0::1;::::0;::::1;23122:21:1::0;23179:2;23159:18;;;23152:30;23218:29;23198:18;;;23191:57;23265:18;;92866:75:0::1;22938:351:1::0;92866:75:0::1;93064:12;::::0;93024:96:::1;::::0;-1:-1:-1;;;;;93064:12:0::1;93079:14:::0;93103:4:::1;93110:9:::0;93024:31:::1;:96::i;:::-;93266:12;::::0;93295:18:::1;::::0;;93266:60:::1;::::0;;;;-1:-1:-1;;;;;93295:18:0;;::::1;93266:60:::0;;::::1;20485:74:1::0;;;;20575:18;;;20568:34;;;93266:12:0;;::::1;::::0;:20:::1;::::0;20458:18:1;;93266:60:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;93337:18:0::1;::::0;;:35:::1;::::0;;;;;;::::1;1786:25:1::0;;;-1:-1:-1;;;;;93337:18:0::1;::::0;:24:::1;::::0;1759:18:1;;93337:35:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;93432:23;93458:20;93473:4;93458:14;:20::i;:::-;-1:-1:-1::0;;;;;93577:33:0;::::1;93489:14;93577:33:::0;;;:17:::1;:33:::0;;;;;;;;93516:95;;26390:66:1;26377:2;26373:15;;;26369:88;93516:95:0;;::::1;26357:101:1::0;;;;26474:12;;;26467:28;;;26511:12;;;26504:28;;;26548:12;;;26541:28;93432:46:0;;-1:-1:-1;93489:14:0;26585:13:1;;93516:95:0::1;::::0;;;;;::::1;::::0;;;;;;93506:106;;93516:95:::1;93506:106:::0;;::::1;::::0;-1:-1:-1;;;;;93669:28:0;::::1;;::::0;;;:12:::1;:28:::0;;;;;93703:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;93506:106;;-1:-1:-1;93669:28:0;93703:164;;;93804:22:::1;93822:4:::0;93750:15;93804:22:::1;:::i;:::-;93703:164:::0;;::::1;::::0;;::::1;::::0;;;93669:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;93669: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;93912:47:::1;::::0;93927:14;;93943:9;;93912:14:::1;:47::i;:::-;93977:68;::::0;;26840:25:1;;;26896:2;26881:18;;26874:34;;;26924:18;;;26917:34;;;-1:-1:-1;;;;;26987:55:1;;;26982:2;26967:18;;26960:83;93977:68:0;::::1;::::0;::::1;::::0;26827:3:1;26812:19;93977:68:0::1;;;;;;;94065:6:::0;92406:1673;-1:-1:-1;;;;;;;;;92406:1673:0:o;40041:133::-;40100:7;40127:39;40136:15;40153:12;;40127:8;:39::i;:::-;40120:46;;40041:133;:::o;56355:1313::-;56503:31;56478:8;56488:4;37175:49;37199:7;37208:8;37218:5;37175:23;:49::i;:::-;56602:22:::1;::::0;;;::::1;;;56601:23;56593:60;;;::::0;-1:-1:-1;;;56593:60:0;;14383:2:1;56593:60:0::1;::::0;::::1;14365:21:1::0;14422:2;14402:18;;;14395:30;14461:26;14441:18;;;14434:54;14505:18;;56593:60:0::1;14181:348:1::0;56593:60:0::1;56736:23;::::0;;;::::1;;;:32;56728:70;;;::::0;-1:-1:-1;;;56728:70:0;;14736:2:1;56728:70:0::1;::::0;::::1;14718:21:1::0;14775:2;14755:18;;;14748:30;14814:27;14794:18;;;14787:55;14859:18;;56728:70:0::1;14534:349:1::0;56728:70:0::1;-1:-1:-1::0;;;;;56897:29:0;::::1;;::::0;;;:19:::1;:29;::::0;;;;56929:15:::1;56897:47:::0;;57056:12:::1;:19:::0;57042:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;57042:34:0::1;;57025:51;;57094:9;57089:419;57113:12;:19:::0;57109:23;::::1;57089:419;;;-1:-1:-1::0;;;;;57174:17:0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;57154:17;;:14;;57192:1;;57154:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;-1:-1:-1;;;;;57209:17:0;::::1;57232:1;57209:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;57252:17;;:14;;57227:1;;57252:17;::::1;;;;;:::i;:::-;;;;;;;:21;57248:249;;;57294:84;57322:12;57335:1;57322:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;57322:15:0::1;57339:19;57360:14;57375:1;57360:17;;;;;;;;:::i;:::-;;;;;;;57294:27;:84::i;:::-;57415:8;-1:-1:-1::0;;;;;57404:77:0::1;;57425:14;57440:1;57425:17;;;;;;;;:::i;:::-;;;;;;;57444:12;57457:1;57444:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;57404:77:::1;::::0;;27256:25:1;;;-1:-1:-1;;;;;57444:15:0;;::::1;27358:18:1::0;;;27351:43;;;;27430:15;;27410:18;;;27403:43;27244:2;27229:18;57404:77:0::1;;;;;;;57248:249;57134:3;;57089:419;;;;56355:1313:::0;;;;;;;:::o;26099:361::-;26294:45;;;-1:-1:-1;;;;;20503:55:1;;;26294:45:0;;;20485:74:1;20575:18;;;;20568:34;;;26294:45:0;;;;;;;;;;20458:18:1;;;;26294:45:0;;;;;;;;;;;;;26283:57;;-1:-1:-1;;;;26283:10:0;;;;:57;;26294:45;26283:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26247:93;;;;26359:7;:57;;;;-1:-1:-1;26371:11:0;;:16;;:44;;;26402:4;26391:24;;;;;;;;;;;;:::i;:::-;26351:101;;;;-1:-1:-1;;;26351:101:0;;27951:2:1;26351:101:0;;;27933:21:1;27990:2;27970:18;;;27963:30;28029:33;28009:18;;;28002:61;28080:18;;26351:101:0;27749:355:1;26351:101:0;26169:291;;26099:361;;;:::o;87990:590::-;88072:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88072:31:0;88105:15;88137:11;;88133:347;;88170:9;88165:304;-1:-1:-1;;;;;88189:28:0;;;;;;:12;:28;;;;;:35;88185:39;;88165:304;;;-1:-1:-1;;;;;88264:28:0;;;;;;:12;:28;;;;;:31;;88293:1;;88264:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;88254:6;:48;88250:204;;-1:-1:-1;;;;;88341:28:0;;;;;;:12;:28;;;;;:31;;88370:1;;88341:31;;;;;;:::i;:::-;;;;;;;;;;;88326:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88405:1;88395:11;;88429:5;;88250:204;88226:3;;88165:304;;;;88133:347;88498:11;;;;;:44;;-1:-1:-1;88513:19:0;;:29;;88498:44;88490:72;;;;-1:-1:-1;;;88490:72:0;;28311:2:1;88490:72:0;;;28293:21:1;28350:2;28330:18;;;28323:30;28389:17;28369:18;;;28362:45;28424:18;;88490:72:0;28109:339:1;88490:72:0;87990:590;;;;;:::o;26468:402::-;26693:51;;;-1:-1:-1;;;;;28734:15:1;;;26693:51:0;;;28716:34:1;28786:15;;;28766:18;;;28759:43;28818:18;;;;28811:34;;;26693:51:0;;;;;;;;;;28628:18:1;;;;26693:51:0;;;;;;;;;;;;;26682:63;;-1:-1:-1;;;;26682:10:0;;;;:63;;26693:51;26682:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26646:99;;;;26764:7;:57;;;;-1:-1:-1;26776:11:0;;:16;;:44;;;26807:4;26796:24;;;;;;;;;;;;:::i;:::-;26756:106;;;;-1:-1:-1;;;26756:106:0;;29058:2:1;26756:106:0;;;29040:21:1;29097:2;29077:18;;;29070:30;29136:34;29116:18;;;29109:62;29207:6;29187:18;;;29180:34;29231:19;;26756:106:0;28856:400:1;26756:106:0;26556:314;;26468:402;;;;:::o;87105:877::-;87233:17;87253:27;87265:14;87253:11;:27::i;:::-;87233:47;;87297:6;87293:561;;;87388:3;87361:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;87406:33:0;;;;;;:17;:33;;;;;:40;;87443:3;;87406:33;:40;;87443:3;;87406:40;:::i;:::-;;;;-1:-1:-1;;;;;;;87500:23:0;;;87496:64;;-1:-1:-1;;;;;87525:28:0;;;;;;:17;:28;;;;;:35;;87557:3;;87525:28;:35;;87557:3;;87525:35;:::i;:::-;;;;-1:-1:-1;;87496:64:0;87293:561;;;87670:3;87643:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;87688:33:0;;;;;;:17;:33;;;;;:40;;87725:3;;87688:33;:40;;87725:3;;87688:40;:::i;:::-;;;;-1:-1:-1;;;;;;;87782:23:0;;;87778:64;;-1:-1:-1;;;;;87807:28:0;;;;;;:17;:28;;;;;:35;;87839:3;;87807:28;:35;;87839:3;;87807:35;:::i;:::-;;;;-1:-1:-1;;87778:64:0;87922:52;87946:14;87962:5;87969:4;52023:1962;52209:22;;;;;;;52204:214;;52357:8;52353:54;;;52385:6;:4;:6::i;:::-;52558:19;52554:109;;;52627:24;52643:7;52627:15;:24::i;:::-;-1:-1:-1;;;;;52593:31:0;;;;;;:22;:31;;;;;:58;52554:109;-1:-1:-1;;;;;52687:21:0;;;52683:1295;;52901:27;52947:28;52994:27;53039:30;53061:7;53039:21;:30::i;:::-;53136:22;;52879:190;;-1:-1:-1;52879:190:0;;-1:-1:-1;52879:190:0;-1:-1:-1;53136:22:0;;;;;53131:49;;53160:20;53172:7;53160:11;:20::i;:::-;-1:-1:-1;;;;;53256:31:0;;;;;;:22;:31;;;;;:54;;;53397:42;;;53393:572;;53460:19;53482:41;53504:19;53482;:41;:::i;:::-;53460:63;;53592:11;53567:22;;:36;;;;:::i;:::-;53542:22;:61;53651:33;53673:11;53651:19;:33;:::i;:::-;-1:-1:-1;;;;;53622:26:0;;;;;;:17;:26;;;;;:62;-1:-1:-1;53393:572:0;;;53725:19;53747:41;53769:19;53747;:41;:::i;:::-;53725:63;;53857:11;53832:22;;:36;;;;:::i;:::-;53807:22;:61;53916:33;53938:11;53916:19;:33;:::i;:::-;-1:-1:-1;;;;;53887:26:0;;;;;;:17;:26;;;;;:62;-1:-1:-1;52710:1268:0;;;52023:1962;;;:::o;57755:4810::-;57842:29;:27;:29::i;:::-;57961:9;57956:327;57980:18;:25;57976:29;;57956:327;;;58027:34;58064:18;58083:1;58064:21;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;58064:21:0;;-1:-1:-1;58104:40:0;;58100:172;;58165:91;;;;;58250:4;58165:91;;;4901:74:1;-1:-1:-1;;;;;58165:76:0;;;;;4874:18:1;;58165:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;58100:172;-1:-1:-1;58007:3:0;;57956:327;;;;58643:27;34616:6;58699:12;;58681:15;:30;;;;:::i;:::-;58673:57;;;;:::i;:::-;58643:87;;58869:9;58864:284;58888:12;:19;58884:23;;58864:284;;;59010:12;59023:1;59010:15;;;;;;;;:::i;:::-;;;;;;;;;;;59003:48;;;;;59045:4;59003:48;;;4901:74:1;-1:-1:-1;;;;;59010:15:0;;;;59003:33;;4874:18:1;;59003:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58974:23;:19;58996:1;58974:23;:::i;:::-;34616:6;58938:14;58950:1;58938:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;58937:114;;59117:12;59130:1;59117:15;;;;;;;;:::i;:::-;;;;;;;;;;;;59060:73;;;29753:34:1;59060:73:0;;;29741:47:1;;;;29818:6;29804:12;;;29797:28;29863:2;29859:15;;;29841:12;;;29834:110;29960:12;;59060:73:0;;;;;;;;;;;;58929:207;;;;;-1:-1:-1;;;58929:207:0;;;;;;;;:::i;:::-;-1:-1:-1;58909:3:0;;58864:284;;;-1:-1:-1;34616:6:0;59360:23;:19;59382:1;59360:23;:::i;:::-;59359:43;;;;:::i;:::-;59343:12;;:60;;;;:::i;:::-;59328:12;:75;59742:17;:20;;59760:1;;59742:20;;;;;;:::i;:::-;;;;;;;;;59766:1;59742:25;59738:743;;59864:19;59893:12;59906:1;59893:15;;;;;;;;:::i;:::-;;;;;;;;;;;59886:48;;;;;59928:4;59886:48;;;4901:74:1;-1:-1:-1;;;;;59893:15:0;;;;59886:33;;4874:18:1;;59886:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59864:70;;59949:18;59977:12;59990:1;59977:15;;;;;;;;:::i;:::-;;;;;;;;;;;59970:48;;;;;60012:4;59970:48;;;4901:74:1;-1:-1:-1;;;;;59977:15:0;;;;59970:33;;4874:18:1;;59970:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60033:18;;;:49;;;;;60070:4;60033:49;;;30151:74:1;;;;60033:18:0;30241::1;;;30234:50;59949:69:0;;-1:-1:-1;;;;;;60033:18:0;;;;:28;;30124:18:1;;60033:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;60097:18;60125:12;60138:1;60125:15;;;;;;;;:::i;:::-;;;;;;;;;;;60118:48;;;;;60160:4;60118:48;;;4901:74:1;-1:-1:-1;;;;;60125:15:0;;;;60118:33;;4874:18:1;;60118:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60097:69;;60181:17;60208:12;60221:1;60208:15;;;;;;;;:::i;:::-;;;;;;;;;;;60201:48;;;;;60243:4;60201:48;;;4901:74:1;-1:-1:-1;;;;;60208:15:0;;;;60201:33;;4874:18:1;;60201:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60181:68;-1:-1:-1;34616:6:0;60331:24;60344:11;60331:10;:24;:::i;:::-;60330:44;;;;:::i;:::-;60307:17;60325:1;60307:20;;;;;;;;:::i;:::-;;;;;;;;;;:67;34616:6;60421:22;60433:10;60421:9;:22;:::i;:::-;60420:42;;;;:::i;:::-;60397:17;60415:1;60397:20;;;;;;;;:::i;:::-;;;;;;;;;;:65;-1:-1:-1;;;;59738:743:0;62528:29;62573:435;62660:34;62697:17;:15;:17::i;:::-;62660:54;;62777:9;62772:133;62796:21;:28;62792:32;;62772:133;;;62873:17;62891:1;62873:20;;;;;;;;:::i;:::-;;;;;;;62846:21;62868:1;62846:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;62826:3;;62772:133;;;;62974:26;:24;:26::i;:::-;62957:14;:43;-1:-1:-1;62573:435:0:o;53993:585::-;-1:-1:-1;;;;;54055:21:0;;;54051:520;;54132:27;54162:15;54169:7;54162:6;:15::i;:::-;54132:45;;54240:9;54235:118;54259:10;:17;54255:1;:21;54235:118;;;54324:10;54335:1;54324:13;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;54302:16:0;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;54278:3;;54235:118;;;;54420:9;54415:145;54439:10;:17;54435:1;:21;54415:145;;;54520:21;54542:1;54520:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;54482:32:0;;;;:23;:32;;;;;;:35;;;;;;;;:62;54458:3;;54415:145;;14:154:1;-1:-1:-1;;;;;93:5:1;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;1822:180::-;1881:6;1934:2;1922:9;1913:7;1909:23;1905:32;1902:52;;;1950:1;1947;1940:12;1902:52;-1:-1:-1;1973:23:1;;1822:180;-1:-1:-1;1822:180:1:o;2007:681::-;2178:2;2230:21;;;2300:13;;2203:18;;;2322:22;;;2149:4;;2178:2;2401:15;;;;2375:2;2360:18;;;2149:4;2444:218;2458:6;2455:1;2452:13;2444:218;;;2523:13;;-1:-1:-1;;;;;2519:62:1;2507:75;;2637:15;;;;2602:12;;;;2480:1;2473:9;2444:218;;2693:248;2761:6;2769;2822:2;2810:9;2801:7;2797:23;2793:32;2790:52;;;2838:1;2835;2828:12;2790:52;-1:-1:-1;;2861:23:1;;;2931:2;2916:18;;;2903:32;;-1:-1:-1;2693:248:1:o;3128:1011::-;3357:2;3409:21;;;3479:13;;3382:18;;;3501:22;;;3328:4;;3357:2;3542;;3560:18;;;;3601:15;;;3328:4;3644:469;3658:6;3655:1;3652:13;3644:469;;;3717:13;;3755:9;;3743:22;;3805:11;;;3799:18;3785:12;;;3778:40;3858:11;;;3852:18;3838:12;;;3831:40;3894:4;3938:11;;;3932:18;3918:12;;;3911:40;3974:4;4018:11;;;4012:18;3998:12;;;3991:40;4060:4;4051:14;;;;4088:15;;;;3680:1;3673:9;3644:469;;;-1:-1:-1;4130:3:1;;3128:1011;-1:-1:-1;;;;;;;3128:1011:1:o;4144:388::-;4212:6;4220;4273:2;4261:9;4252:7;4248:23;4244:32;4241:52;;;4289:1;4286;4279:12;4241:52;4328:9;4315:23;4347:31;4372:5;4347:31;:::i;:::-;4397:5;-1:-1:-1;4454:2:1;4439:18;;4426:32;4467:33;4426:32;4467:33;:::i;:::-;4519:7;4509:17;;;4144:388;;;;;:::o;5217:647::-;5291:6;5299;5307;5315;5368:3;5356:9;5347:7;5343:23;5339:33;5336:53;;;5385:1;5382;5375:12;5336:53;5424:9;5411:23;5443:28;5465:5;5443:28;:::i;:::-;5490:5;-1:-1:-1;5547:2:1;5532:18;;5519:32;5560:30;5519:32;5560:30;:::i;:::-;5609:7;-1:-1:-1;5668:2:1;5653:18;;5640:32;5681:30;5640:32;5681:30;:::i;:::-;5730:7;-1:-1:-1;5789:2:1;5774:18;;5761:32;5802:30;5761:32;5802:30;:::i;:::-;5217:647;;;;-1:-1:-1;5217:647:1;;-1:-1:-1;;5217:647:1:o;5869:250::-;5954:1;5964:113;5978:6;5975:1;5972:13;5964:113;;;6054:11;;;6048:18;6035:11;;;6028:39;6000:2;5993:10;5964:113;;;-1:-1:-1;;6111:1:1;6093:16;;6086:27;5869:250::o;6124:455::-;6273:2;6262:9;6255:21;6236:4;6305:6;6299:13;6348:6;6343:2;6332:9;6328:18;6321:34;6364:79;6436:6;6431:2;6420:9;6416:18;6411:2;6403:6;6399:15;6364:79;:::i;:::-;6495:2;6483:15;6500:66;6479:88;6464:104;;;;6570:2;6460:113;;6124:455;-1:-1:-1;;6124:455:1:o;7097:315::-;7165:6;7173;7226:2;7214:9;7205:7;7201:23;7197:32;7194:52;;;7242:1;7239;7232:12;7194:52;7281:9;7268:23;7300:31;7325:5;7300:31;:::i;:::-;7350:5;7402:2;7387:18;;;;7374:32;;-1:-1:-1;;;7097:315:1:o;7417:382::-;7482:6;7490;7543:2;7531:9;7522:7;7518:23;7514:32;7511:52;;;7559:1;7556;7549:12;7511:52;7598:9;7585:23;7617:31;7642:5;7617:31;:::i;:::-;7667:5;-1:-1:-1;7724:2:1;7709:18;;7696:32;7737:30;7696:32;7737:30;:::i;9283:598::-;9369:6;9377;9385;9393;9446:3;9434:9;9425:7;9421:23;9417:33;9414:53;;;9463:1;9460;9453:12;9414:53;9502:9;9489:23;9521:31;9546:5;9521:31;:::i;:::-;9571:5;-1:-1:-1;9623:2:1;9608:18;;9595:32;;-1:-1:-1;9679:2:1;9664:18;;9651:32;9692:33;9651:32;9692:33;:::i;:::-;9744:7;-1:-1:-1;9803:2:1;9788:18;;9775:32;9816:33;9775:32;9816:33;:::i;9886:241::-;9942:6;9995:2;9983:9;9974:7;9970:23;9966:32;9963:52;;;10011:1;10008;10001:12;9963:52;10050:9;10037:23;10069:28;10091:5;10069:28;:::i;10132:184::-;10184:77;10181:1;10174:88;10281:4;10278:1;10271:15;10305:4;10302:1;10295:15;10321:334;10392:2;10386:9;10448:2;10438:13;;10453:66;10434:86;10422:99;;10551:18;10536:34;;10572:22;;;10533:62;10530:88;;;10598:18;;:::i;:::-;10634:2;10627:22;10321:334;;-1:-1:-1;10321:334:1:o;10660:761::-;10742:6;10795:3;10783:9;10774:7;10770:23;10766:33;10763:53;;;10812:1;10809;10802:12;10763:53;10861:7;10854:4;10843:9;10839:20;10835:34;10825:62;;10883:1;10880;10873:12;10825:62;10916:2;10910:9;10958:3;10950:6;10946:16;11028:6;11016:10;11013:22;10992:18;10980:10;10977:34;10974:62;10971:88;;;11039:18;;:::i;:::-;11075:2;11068:22;11110:6;11154:3;11139:19;;11170;;;11167:39;;;11202:1;11199;11192:12;11167:39;11226:9;11244:146;11260:6;11255:3;11252:15;11244:146;;;11328:17;;11316:30;;11375:4;11366:14;;;;11277;11244:146;;;-1:-1:-1;11409:6:1;;10660:761;-1:-1:-1;;;;;10660:761:1:o;11426:184::-;11478:77;11475:1;11468:88;11575:4;11572:1;11565:15;11599:4;11596:1;11589:15;11615:184;11667:77;11664:1;11657:88;11764:4;11761:1;11754:15;11788:4;11785:1;11778:15;11804:128;11871:9;;;11892:11;;;11889:37;;;11906:18;;:::i;11937:168::-;12010:9;;;12041;;12058:15;;;12052:22;;12038:37;12028:71;;12079:18;;:::i;12110:274::-;12150:1;12176;12166:189;;12211:77;12208:1;12201:88;12312:4;12309:1;12302:15;12340:4;12337:1;12330:15;12166:189;-1:-1:-1;12369:9:1;;12110:274::o;12389:125::-;12454:9;;;12475:10;;;12472:36;;;12488:18;;:::i;13642:184::-;13712:6;13765:2;13753:9;13744:7;13740:23;13736:32;13733:52;;;13781:1;13778;13771:12;13733:52;-1:-1:-1;13804:16:1;;13642:184;-1:-1:-1;13642:184:1:o;14888:437::-;14967:1;14963:12;;;;15010;;;15031:61;;15085:4;15077:6;15073:17;15063:27;;15031:61;15138:2;15130:6;15127:14;15107:18;15104:38;15101:218;;15175:77;15172:1;15165:88;15276:4;15273:1;15266:15;15304:4;15301:1;15294:15;15519:183;15579:4;15612:18;15604:6;15601:30;15598:56;;;15634:18;;:::i;:::-;-1:-1:-1;15679:1:1;15675:14;15691:4;15671:25;;15519:183::o;15707:665::-;15772:5;15825:3;15818:4;15810:6;15806:17;15802:27;15792:55;;15843:1;15840;15833:12;15792:55;15872:6;15866:13;15898:4;15922:60;15938:43;15978:2;15938:43;:::i;:::-;15922:60;:::i;:::-;16004:3;16028:2;16023:3;16016:15;16056:4;16051:3;16047:14;16040:21;;16113:4;16107:2;16104:1;16100:10;16092:6;16088:23;16084:34;16070:48;;16141:3;16133:6;16130:15;16127:35;;;16158:1;16155;16148:12;16127:35;16194:4;16186:6;16182:17;16208:135;16224:6;16219:3;16216:15;16208:135;;;16290:10;;16278:23;;16321:12;;;;16241;;16208:135;;;-1:-1:-1;16361:5:1;15707:665;-1:-1:-1;;;;;;15707:665:1:o;16377:1270::-;16515:6;16523;16531;16584:2;16572:9;16563:7;16559:23;16555:32;16552:52;;;16600:1;16597;16590:12;16552:52;16633:9;16627:16;16662:18;16703:2;16695:6;16692:14;16689:34;;;16719:1;16716;16709:12;16689:34;16757:6;16746:9;16742:22;16732:32;;16802:7;16795:4;16791:2;16787:13;16783:27;16773:55;;16824:1;16821;16814:12;16773:55;16853:2;16847:9;16875:4;16899:60;16915:43;16955:2;16915:43;:::i;16899:60::-;16993:15;;;17075:1;17071:10;;;;17063:19;;17059:28;;;17024:12;;;;17099:19;;;17096:39;;;17131:1;17128;17121:12;17096:39;17155:11;;;;17175:210;17191:6;17186:3;17183:15;17175:210;;;17264:3;17258:10;17281:31;17306:5;17281:31;:::i;:::-;17325:18;;17208:12;;;;17363;;;;17175:210;;;17440:18;;;17434:25;17404:5;;-1:-1:-1;17434:25:1;;-1:-1:-1;;;17471:16:1;;;17468:36;;;17500:1;17497;17490:12;17468:36;;17523:74;17589:7;17578:8;17567:9;17563:24;17523:74;:::i;:::-;17513:84;;;17637:2;17626:9;17622:18;17616:25;17606:35;;16377:1270;;;;;:::o;19018:245::-;19085:6;19138:2;19126:9;19117:7;19113:23;19109:32;19106:52;;;19154:1;19151;19144:12;19106:52;19186:9;19180:16;19205:28;19227:5;19205:28;:::i;20866:179::-;20944:13;;20997:22;20986:34;;20976:45;;20966:73;;21035:1;21032;21025:12;21050:473;21153:6;21161;21169;21177;21185;21238:3;21226:9;21217:7;21213:23;21209:33;21206:53;;;21255:1;21252;21245:12;21206:53;21278:39;21307:9;21278:39;:::i;:::-;21268:49;;21357:2;21346:9;21342:18;21336:25;21326:35;;21401:2;21390:9;21386:18;21380:25;21370:35;;21445:2;21434:9;21430:18;21424:25;21414:35;;21468:49;21512:3;21501:9;21497:19;21468:49;:::i;:::-;21458:59;;21050:473;;;;;;;;:::o;27457:287::-;27586:3;27624:6;27618:13;27640:66;27699:6;27694:3;27687:4;27679:6;27675:17;27640:66;:::i;:::-;27722:16;;;;;27457:287;-1:-1:-1;;27457:287:1:o;29261:245::-;29340:6;29348;29401:2;29389:9;29380:7;29376:23;29372:32;29369:52;;;29417:1;29414;29407:12;29369:52;-1:-1:-1;;29440:16:1;;29496:2;29481:18;;;29475:25;29440:16;;29475:25;;-1:-1:-1;29261:245:1:o
Swarm Source
ipfs://3224042895f099e06381ae413bdb9836d4967292f17612d7df8e1595a897805a
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1.39
Net Worth in ETH
0.000684
Token Allocations
FXS
63.70%
BAL
26.46%
AURA
9.83%
Multichain Portfolio | 33 Chains
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.