Source Code
Latest 25 from a total of 619 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Sync | 24407586 | 14 days ago | IN | 0 ETH | 0.00001352 | ||||
| Get Reward | 22144234 | 330 days ago | IN | 0 ETH | 0.00024627 | ||||
| Get Reward | 21588865 | 408 days ago | IN | 0 ETH | 0.00299768 | ||||
| Withdraw Locked | 21210800 | 461 days ago | IN | 0 ETH | 0.00429297 | ||||
| Sync | 21199950 | 462 days ago | IN | 0 ETH | 0.00109925 | ||||
| Get Reward | 21199782 | 462 days ago | IN | 0 ETH | 0.00570967 | ||||
| Sync | 20602171 | 546 days ago | IN | 0 ETH | 0.00009145 | ||||
| Sync | 20602165 | 546 days ago | IN | 0 ETH | 0.00008907 | ||||
| Sync | 20602163 | 546 days ago | IN | 0 ETH | 0.00008925 | ||||
| Sync | 20602162 | 546 days ago | IN | 0 ETH | 0.00009043 | ||||
| Sync | 20602116 | 546 days ago | IN | 0 ETH | 0.00009304 | ||||
| Sync | 20602112 | 546 days ago | IN | 0 ETH | 0.00008612 | ||||
| Sync | 20602108 | 546 days ago | IN | 0 ETH | 0.00018256 | ||||
| Sync | 20530557 | 556 days ago | IN | 0 ETH | 0.0003311 | ||||
| Sync | 19756371 | 664 days ago | IN | 0 ETH | 0.00102688 | ||||
| Withdraw Locked | 19296019 | 728 days ago | IN | 0 ETH | 0.01472393 | ||||
| Sync | 19073396 | 760 days ago | IN | 0 ETH | 0.00072437 | ||||
| Sync | 18751983 | 805 days ago | IN | 0 ETH | 0.00864809 | ||||
| Get Reward | 18525128 | 837 days ago | IN | 0 ETH | 0.00587213 | ||||
| Withdraw Locked | 18389551 | 855 days ago | IN | 0 ETH | 0.00409852 | ||||
| Get Reward | 18389549 | 855 days ago | IN | 0 ETH | 0.0039138 | ||||
| Sync | 18114117 | 894 days ago | IN | 0 ETH | 0.00543162 | ||||
| Get Reward | 17981830 | 913 days ago | IN | 0 ETH | 0.00333598 | ||||
| Stake Locked | 17981829 | 913 days ago | IN | 0 ETH | 0.00861052 | ||||
| Get Reward | 17981584 | 913 days ago | IN | 0 ETH | 0.00548829 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
FraxUnifiedFarm_PosRebase_aFRAX
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2022-04-22
*/
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
// Sources flattened with hardhat v2.9.3 https://hardhat.org
// File contracts/Math/Math.sol
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow, so we distribute
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
// File contracts/Curve/IveFXS.sol
pragma abicoder v2;
interface IveFXS {
struct LockedBalance {
int128 amount;
uint256 end;
}
function commit_transfer_ownership(address addr) external;
function apply_transfer_ownership() external;
function commit_smart_wallet_checker(address addr) external;
function apply_smart_wallet_checker() external;
function toggleEmergencyUnlock() external;
function recoverERC20(address token_addr, uint256 amount) external;
function get_last_user_slope(address addr) external view returns (int128);
function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256);
function locked__end(address _addr) external view returns (uint256);
function checkpoint() external;
function deposit_for(address _addr, uint256 _value) external;
function create_lock(uint256 _value, uint256 _unlock_time) external;
function increase_amount(uint256 _value) external;
function increase_unlock_time(uint256 _unlock_time) external;
function withdraw() external;
function balanceOf(address addr) external view returns (uint256);
function balanceOf(address addr, uint256 _t) external view returns (uint256);
function balanceOfAt(address addr, uint256 _block) external view returns (uint256);
function totalSupply() external view returns (uint256);
function totalSupply(uint256 t) external view returns (uint256);
function totalSupplyAt(uint256 _block) external view returns (uint256);
function totalFXSSupply() external view returns (uint256);
function totalFXSSupplyAt(uint256 _block) external view returns (uint256);
function changeController(address _newController) external;
function token() external view returns (address);
function supply() external view returns (uint256);
function locked(address addr) external view returns (LockedBalance memory);
function epoch() external view returns (uint256);
function point_history(uint256 arg0) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt);
function user_point_history(address arg0, uint256 arg1) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt);
function user_point_epoch(address arg0) external view returns (uint256);
function slope_changes(uint256 arg0) external view returns (int128);
function controller() external view returns (address);
function transfersEnabled() external view returns (bool);
function emergencyUnlockActive() external view returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function version() external view returns (string memory);
function decimals() external view returns (uint256);
function future_smart_wallet_checker() external view returns (address);
function smart_wallet_checker() external view returns (address);
function admin() external view returns (address);
function future_admin() external view returns (address);
}
// File contracts/Curve/IFraxGaugeController.sol
// https://github.com/swervefi/swerve/edit/master/packages/swerve-contracts/interfaces/IGaugeController.sol
interface IFraxGaugeController {
struct Point {
uint256 bias;
uint256 slope;
}
struct VotedSlope {
uint256 slope;
uint256 power;
uint256 end;
}
// Public variables
function admin() external view returns (address);
function future_admin() external view returns (address);
function token() external view returns (address);
function voting_escrow() external view returns (address);
function n_gauge_types() external view returns (int128);
function n_gauges() external view returns (int128);
function gauge_type_names(int128) external view returns (string memory);
function gauges(uint256) external view returns (address);
function vote_user_slopes(address, address)
external
view
returns (VotedSlope memory);
function vote_user_power(address) external view returns (uint256);
function last_user_vote(address, address) external view returns (uint256);
function points_weight(address, uint256)
external
view
returns (Point memory);
function time_weight(address) external view returns (uint256);
function points_sum(int128, uint256) external view returns (Point memory);
function time_sum(uint256) external view returns (uint256);
function points_total(uint256) external view returns (uint256);
function time_total() external view returns (uint256);
function points_type_weight(int128, uint256)
external
view
returns (uint256);
function time_type_weight(uint256) external view returns (uint256);
// Getter functions
function gauge_types(address) external view returns (int128);
function gauge_relative_weight(address) external view returns (uint256);
function gauge_relative_weight(address, uint256) external view returns (uint256);
function get_gauge_weight(address) external view returns (uint256);
function get_type_weight(int128) external view returns (uint256);
function get_total_weight() external view returns (uint256);
function get_weights_sum_per_type(int128) external view returns (uint256);
// External functions
function commit_transfer_ownership(address) external;
function apply_transfer_ownership() external;
function add_gauge(
address,
int128,
uint256
) external;
function checkpoint() external;
function checkpoint_gauge(address) external;
function global_emission_rate() external view returns (uint256);
function gauge_relative_weight_write(address)
external
returns (uint256);
function gauge_relative_weight_write(address, uint256)
external
returns (uint256);
function add_type(string memory, uint256) external;
function change_type_weight(int128, uint256) external;
function change_gauge_weight(address, uint256) external;
function change_global_emission_rate(uint256) external;
function vote_for_gauge_weights(address, uint256) external;
}
// File contracts/Curve/IFraxGaugeFXSRewardsDistributor.sol
interface IFraxGaugeFXSRewardsDistributor {
function acceptOwnership() external;
function curator_address() external view returns(address);
function currentReward(address gauge_address) external view returns(uint256 reward_amount);
function distributeReward(address gauge_address) external returns(uint256 weeks_elapsed, uint256 reward_tally);
function distributionsOn() external view returns(bool);
function gauge_whitelist(address) external view returns(bool);
function is_middleman(address) external view returns(bool);
function last_time_gauge_paid(address) external view returns(uint256);
function nominateNewOwner(address _owner) external;
function nominatedOwner() external view returns(address);
function owner() external view returns(address);
function recoverERC20(address tokenAddress, uint256 tokenAmount) external;
function setCurator(address _new_curator_address) external;
function setGaugeController(address _gauge_controller_address) external;
function setGaugeState(address _gauge_address, bool _is_middleman, bool _is_active) external;
function setTimelock(address _new_timelock) external;
function timelock_address() external view returns(address);
function toggleDistributions() external;
}
// File contracts/Common/Context.sol
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File contracts/Math/SafeMath.sol
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File contracts/ERC20/IERC20.sol
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File contracts/Utils/Address.sol
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File contracts/ERC20/ERC20.sol
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20Mintable}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory __name, string memory __symbol) public {
_name = __name;
_symbol = __symbol;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
* called.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.approve(address spender, uint256 amount)
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20};
*
* Requirements:
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for `sender`'s tokens of at least
* `amount`.
*/
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for `accounts`'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), decreasedAllowance);
_burn(account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
*
* This is internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Destroys `amount` tokens from `account`.`amount` is then deducted
* from the caller's allowance.
*
* See {_burn} and {_approve}.
*/
function _burnFrom(address account, uint256 amount) internal virtual {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of `from`'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of `from`'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
// File contracts/Uniswap/TransferHelper.sol
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
// File contracts/ERC20/SafeERC20.sol
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File contracts/Utils/ReentrancyGuard.sol
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
// File contracts/Staking/Owned.sol
// https://docs.synthetix.io/contracts/Owned
contract Owned {
address public owner;
address public nominatedOwner;
constructor (address _owner) public {
require(_owner != address(0), "Owner address cannot be 0");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner {
require(msg.sender == owner, "Only the contract owner may perform this action");
_;
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}
// File contracts/Misc_AMOs/Lending_AMOs/aave/IAaveIncentivesControllerPartial.sol
interface IAaveIncentivesControllerPartial {
/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);
/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must
* be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
* @param amount Amount of rewards to claim
* @param user Address to check and claim rewards
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to
) external returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @return the unclaimed user rewards
*/
function getUserUnclaimedRewards(address user) external view returns (uint256);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function REWARD_TOKEN() external view returns (address);
}
// File contracts/Staking/FraxUnifiedFarmTemplate.sol
pragma experimental ABIEncoderV2;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ====================== FraxUnifiedFarmTemplate =====================
// ====================================================================
// Migratable 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
// Sam Sun: https://github.com/samczsun
// Originally inspired by Synthetix.io, but heavily modified by the Frax team
// (Locked, veFXS, and UniV3 portions are new)
// https://raw.githubusercontent.com/Synthetixio/synthetix/develop/contracts/StakingRewards.sol
// Extra rewards
contract FraxUnifiedFarmTemplate is Owned, ReentrancyGuard {
using SafeERC20 for ERC20;
/* ========== STATE VARIABLES ========== */
// Instances
IveFXS private veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0);
// Frax related
address internal constant frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e;
bool internal frax_is_token0;
uint256 public fraxPerLPStored;
// Constant for various precisions
uint256 internal constant MULTIPLIER_PRECISION = 1e18;
// Time tracking
uint256 public periodFinish;
uint256 public lastUpdateTime;
// Lock time and multiplier settings
uint256 public lock_max_multiplier = uint256(3e18); // E18. 1x = e18
uint256 public lock_time_for_max_multiplier = 3 * 365 * 86400; // 3 years
// uint256 public lock_time_for_max_multiplier = 2 * 86400; // 2 days
uint256 public lock_time_min = 86400; // 1 * 86400 (1 day)
// veFXS related
uint256 public vefxs_boost_scale_factor = uint256(4e18); // E18. 4x = 4e18; 100 / scale_factor = % vefxs supply needed for max boost
uint256 public vefxs_max_multiplier = uint256(2e18); // E18. 1x = 1e18
uint256 public vefxs_per_frax_for_max_boost = uint256(2e18); // E18. 2e18 means 2 veFXS must be held by the staker per 1 FRAX
mapping(address => uint256) internal _vefxsMultiplierStored;
mapping(address => bool) internal valid_vefxs_proxies;
mapping(address => mapping(address => bool)) internal proxy_allowed_stakers;
// Reward addresses, gauge addresses, reward rates, and reward managers
mapping(address => address) public rewardManagers; // token addr -> manager addr
address[] internal rewardTokens;
address[] internal gaugeControllers;
address[] internal rewardDistributors;
uint256[] internal rewardRatesManual;
mapping(address => uint256) public rewardTokenAddrToIdx; // token addr -> token index
// Reward period
uint256 public constant rewardsDuration = 604800; // 7 * 86400 (7 days)
// Reward tracking
uint256[] private rewardsPerTokenStored;
mapping(address => mapping(uint256 => uint256)) private userRewardsPerTokenPaid; // staker addr -> token id -> paid amount
mapping(address => mapping(uint256 => uint256)) private rewards; // staker addr -> token id -> reward amount
mapping(address => uint256) internal lastRewardClaimTime; // staker addr -> timestamp
// Gauge tracking
uint256[] private last_gauge_relative_weights;
uint256[] private last_gauge_time_totals;
// Balance tracking
uint256 internal _total_liquidity_locked;
uint256 internal _total_combined_weight;
mapping(address => uint256) internal _locked_liquidity;
mapping(address => uint256) internal _combined_weights;
mapping(address => uint256) public proxy_lp_balances; // Keeps track of LP balances proxy-wide. Needed to make sure the proxy boost is kept in line
// List of valid migrators (set by governance)
mapping(address => bool) internal valid_migrators;
// Stakers set which migrator(s) they want to use
mapping(address => mapping(address => bool)) internal staker_allowed_migrators;
mapping(address => address) public staker_designated_proxies; // Keep public so users can see on the frontend if they have a proxy
// Admin booleans for emergencies, migrations, and overrides
bool public stakesUnlocked; // Release locked stakes in case of emergency
bool internal migrationsOn; // Used for migrations. Prevents new stakes, but allows LP and reward withdrawals
bool internal withdrawalsPaused; // For emergencies
bool internal rewardsCollectionPaused; // For emergencies
bool internal stakingPaused; // For emergencies
/* ========== STRUCTS ========== */
// In children...
/* ========== MODIFIERS ========== */
modifier onlyByOwnGov() {
require(msg.sender == owner || msg.sender == 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA, "Not owner or timelock");
_;
}
modifier onlyTknMgrs(address reward_token_address) {
require(msg.sender == owner || isTokenManagerFor(msg.sender, reward_token_address), "Not owner or tkn mgr");
_;
}
modifier isMigrating() {
require(migrationsOn == true, "Not in migration");
_;
}
modifier updateRewardAndBalance(address account, bool sync_too) {
_updateRewardAndBalance(account, sync_too);
_;
}
/* ========== CONSTRUCTOR ========== */
constructor (
address _owner,
address[] memory _rewardTokens,
address[] memory _rewardManagers,
uint256[] memory _rewardRatesManual,
address[] memory _gaugeControllers,
address[] memory _rewardDistributors
) Owned(_owner) {
// Address arrays
rewardTokens = _rewardTokens;
gaugeControllers = _gaugeControllers;
rewardDistributors = _rewardDistributors;
rewardRatesManual = _rewardRatesManual;
for (uint256 i = 0; i < _rewardTokens.length; i++){
// For fast token address -> token ID lookups later
rewardTokenAddrToIdx[_rewardTokens[i]] = i;
// Initialize the stored rewards
rewardsPerTokenStored.push(0);
// Initialize the reward managers
rewardManagers[_rewardTokens[i]] = _rewardManagers[i];
// Push in empty relative weights to initialize the array
last_gauge_relative_weights.push(0);
// Push in empty time totals to initialize the array
last_gauge_time_totals.push(0);
}
// Other booleans
stakesUnlocked = false;
// Initialization
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp + rewardsDuration;
}
/* ============= VIEWS ============= */
// ------ REWARD RELATED ------
// See if the caller_addr is a manager for the reward token
function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool){
if (caller_addr == owner) return true; // Contract owner
else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager
return false;
}
// All the reward tokens
function getAllRewardTokens() external view returns (address[] memory) {
return rewardTokens;
}
// Last time the reward was applicable
function lastTimeRewardApplicable() internal view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardRates(uint256 token_idx) public view returns (uint256 rwd_rate) {
address gauge_controller_address = gaugeControllers[token_idx];
if (gauge_controller_address != address(0)) {
rwd_rate = (IFraxGaugeController(gauge_controller_address).global_emission_rate() * last_gauge_relative_weights[token_idx]) / 1e18;
}
else {
rwd_rate = rewardRatesManual[token_idx];
}
}
// Amount of reward tokens per LP token / liquidity unit
function rewardsPerToken() public view returns (uint256[] memory newRewardsPerTokenStored) {
if (_total_liquidity_locked == 0 || _total_combined_weight == 0) {
return rewardsPerTokenStored;
}
else {
newRewardsPerTokenStored = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){
newRewardsPerTokenStored[i] = rewardsPerTokenStored[i] + (
((lastTimeRewardApplicable() - lastUpdateTime) * rewardRates(i) * 1e18) / _total_combined_weight
);
}
return newRewardsPerTokenStored;
}
}
// Amount of reward tokens an account has earned / accrued
// Note: In the edge-case of one of the account's stake expiring since the last claim, this will
// return a slightly inflated number
function earned(address account) public view returns (uint256[] memory new_earned) {
uint256[] memory reward_arr = rewardsPerToken();
new_earned = new uint256[](rewardTokens.length);
if (_combined_weights[account] > 0){
for (uint256 i = 0; i < rewardTokens.length; i++){
new_earned[i] = ((_combined_weights[account] * (reward_arr[i] - userRewardsPerTokenPaid[account][i])) / 1e18)
+ rewards[account][i];
}
}
}
// Total reward tokens emitted in the given period
function getRewardForDuration() external view returns (uint256[] memory rewards_per_duration_arr) {
rewards_per_duration_arr = new uint256[](rewardRatesManual.length);
for (uint256 i = 0; i < rewardRatesManual.length; i++){
rewards_per_duration_arr[i] = rewardRates(i) * rewardsDuration;
}
}
// ------ LIQUIDITY AND WEIGHTS ------
// User locked liquidity / LP tokens
function totalLiquidityLocked() external view returns (uint256) {
return _total_liquidity_locked;
}
// Total locked liquidity / LP tokens
function lockedLiquidityOf(address account) external view returns (uint256) {
return _locked_liquidity[account];
}
// Total combined weight
function totalCombinedWeight() external view returns (uint256) {
return _total_combined_weight;
}
// Total 'balance' used for calculating the percent of the pool the account owns
// Takes into account the locked stake time multiplier and veFXS multiplier
function combinedWeightOf(address account) external view returns (uint256) {
return _combined_weights[account];
}
// Calculated the combined weight for an account
function calcCurCombinedWeight(address account) public virtual view
returns (
uint256 old_combined_weight,
uint256 new_vefxs_multiplier,
uint256 new_combined_weight
)
{
revert("Need cCCW logic");
}
// ------ LOCK RELATED ------
// Multiplier amount, given the length of the lock
function lockMultiplier(uint256 secs) public view returns (uint256) {
return Math.min(
lock_max_multiplier,
uint256(MULTIPLIER_PRECISION) + (
(secs * (lock_max_multiplier - MULTIPLIER_PRECISION)) / lock_time_for_max_multiplier
)
) ;
}
// ------ FRAX RELATED ------
function userStakedFrax(address account) public view returns (uint256) {
return (fraxPerLPStored * _locked_liquidity[account]) / MULTIPLIER_PRECISION;
}
function proxyStakedFrax(address proxy_address) public view returns (uint256) {
return (fraxPerLPStored * proxy_lp_balances[proxy_address]) / MULTIPLIER_PRECISION;
}
// Max LP that can get max veFXS boosted for a given address at its current veFXS balance
function maxLPForMaxBoost(address account) external view returns (uint256) {
return (veFXS.balanceOf(account) * MULTIPLIER_PRECISION * MULTIPLIER_PRECISION) / (vefxs_per_frax_for_max_boost * fraxPerLPStored);
}
// Meant to be overridden
function fraxPerLPToken() public virtual view returns (uint256) {
revert("Need fPLPT logic");
}
// ------ veFXS RELATED ------
function minVeFXSForMaxBoost(address account) public view returns (uint256) {
return (userStakedFrax(account) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION;
}
function minVeFXSForMaxBoostProxy(address proxy_address) public view returns (uint256) {
return (proxyStakedFrax(proxy_address) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION;
}
function getProxyFor(address addr) public view returns (address){
if (valid_vefxs_proxies[addr]) {
// If addr itself is a proxy, return that.
// If it farms itself directly, it should use the shared LP tally in proxyStakedFrax
return addr;
}
else {
// Otherwise, return the proxy, or address(0)
return staker_designated_proxies[addr];
}
}
function veFXSMultiplier(address account) public view returns (uint256 vefxs_multiplier) {
// Use either the user's or their proxy's veFXS balance
uint256 vefxs_bal_to_use = 0;
address the_proxy = getProxyFor(account);
vefxs_bal_to_use = (the_proxy == address(0)) ? veFXS.balanceOf(account) : veFXS.balanceOf(the_proxy);
// First option based on fraction of total veFXS supply, with an added scale factor
uint256 mult_optn_1 = (vefxs_bal_to_use * vefxs_max_multiplier * vefxs_boost_scale_factor)
/ (veFXS.totalSupply() * MULTIPLIER_PRECISION);
// Second based on old method, where the amount of FRAX staked comes into play
uint256 mult_optn_2;
{
uint256 veFXS_needed_for_max_boost;
// Need to use proxy-wide FRAX balance if applicable, to prevent exploiting
veFXS_needed_for_max_boost = (the_proxy == address(0)) ? minVeFXSForMaxBoost(account) : minVeFXSForMaxBoostProxy(the_proxy);
if (veFXS_needed_for_max_boost > 0){
uint256 user_vefxs_fraction = (vefxs_bal_to_use * MULTIPLIER_PRECISION) / veFXS_needed_for_max_boost;
mult_optn_2 = (user_vefxs_fraction * vefxs_max_multiplier) / MULTIPLIER_PRECISION;
}
else mult_optn_2 = 0; // This will happen with the first stake, when user_staked_frax is 0
}
// Select the higher of the two
vefxs_multiplier = (mult_optn_1 > mult_optn_2 ? mult_optn_1 : mult_optn_2);
// Cap the boost to the vefxs_max_multiplier
if (vefxs_multiplier > vefxs_max_multiplier) vefxs_multiplier = vefxs_max_multiplier;
}
/* =============== MUTATIVE FUNCTIONS =============== */
// ------ MIGRATIONS ------
// Staker can allow a migrator
function stakerToggleMigrator(address migrator_address) external {
require(valid_migrators[migrator_address], "Invalid migrator address");
staker_allowed_migrators[msg.sender][migrator_address] = !staker_allowed_migrators[msg.sender][migrator_address];
}
// Proxy can allow a staker to use their veFXS balance (the staker will have to reciprocally toggle them too)
// Must come before 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];
}
}
// Staker can allow a veFXS proxy (the proxy will have to toggle them first)
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");
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 {
// Need to retro-adjust some things if the period hasn't been renewed, then start a new one
if (sync_too){
sync();
}
if (account != address(0)) {
// To keep the math correct, the user's combined weight must be recomputed to account for their
// ever-changing veFXS balance.
(
uint256 old_combined_weight,
uint256 new_vefxs_multiplier,
uint256 new_combined_weight
) = calcCurCombinedWeight(account);
// Calculate the earnings first
_syncEarned(account);
// Update the user's stored veFXS multipliers
_vefxsMultiplierStored[account] = new_vefxs_multiplier;
// Update the user's and the global combined weights
if (new_combined_weight >= old_combined_weight) {
uint256 weight_diff = new_combined_weight - old_combined_weight;
_total_combined_weight = _total_combined_weight + weight_diff;
_combined_weights[account] = old_combined_weight + weight_diff;
} else {
uint256 weight_diff = old_combined_weight - new_combined_weight;
_total_combined_weight = _total_combined_weight - weight_diff;
_combined_weights[account] = old_combined_weight - weight_diff;
}
}
}
function _syncEarned(address account) internal {
if (account != address(0)) {
// Calculate the earnings
uint256[] memory earned_arr = earned(account);
// Update the rewards array
for (uint256 i = 0; i < earned_arr.length; i++){
rewards[account][i] = earned_arr[i];
}
// Update the rewards paid array
for (uint256 i = 0; i < earned_arr.length; i++){
userRewardsPerTokenPaid[account][i] = rewardsPerTokenStored[i];
}
}
}
// ------ REWARDS CLAIMING ------
function getRewardExtraLogic(address destination_address) public nonReentrant {
require(rewardsCollectionPaused == false, "Rewards collection paused");
return _getRewardExtraLogic(msg.sender, destination_address);
}
function _getRewardExtraLogic(address rewardee, address destination_address) internal virtual {
revert("Need gREL logic");
}
// Two different getReward functions are needed because of delegateCall and msg.sender issues
// For backwards-compatibility
function getReward(address destination_address) external nonReentrant returns (uint256[] memory) {
return _getReward(msg.sender, destination_address, true);
}
function getReward2(address destination_address, bool claim_extra_too) external nonReentrant returns (uint256[] memory) {
return _getReward(msg.sender, destination_address, claim_extra_too);
}
// No withdrawer == msg.sender check needed since this is only internally callable
function _getReward(address rewardee, address destination_address, bool do_extra_logic) internal updateRewardAndBalance(rewardee, true) returns (uint256[] memory rewards_before) {
// Make sure rewards collection isn't paused
require(rewardsCollectionPaused == false, "Rewards collection paused");
// Update the rewards array and distribute rewards
rewards_before = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardTokens.length; i++){
rewards_before[i] = rewards[rewardee][i];
rewards[rewardee][i] = 0;
if (rewards_before[i] > 0) TransferHelper.safeTransfer(rewardTokens[i], destination_address, rewards_before[i]);
}
// Handle additional reward logic
if (do_extra_logic) {
_getRewardExtraLogic(rewardee, destination_address);
}
// Update the last reward claim time
lastRewardClaimTime[rewardee] = block.timestamp;
}
// ------ FARM SYNCING ------
// If the period expired, renew it
function retroCatchUp() internal {
// Pull in rewards from the rewards distributor, if applicable
for (uint256 i = 0; i < rewardDistributors.length; i++){
address reward_distributor_address = rewardDistributors[i];
if (reward_distributor_address != address(0)) {
IFraxGaugeFXSRewardsDistributor(reward_distributor_address).distributeReward(address(this));
}
}
// Ensure the provided reward amount is not more than the balance in the contract.
// This keeps the reward rate in the right range, preventing overflows due to
// very high values of rewardRate in the earned and rewardsPerToken functions;
// Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
uint256 num_periods_elapsed = uint256(block.timestamp - periodFinish) / rewardsDuration; // Floor division to the nearest period
// Make sure there are enough tokens to renew the reward period
for (uint256 i = 0; i < rewardTokens.length; i++){
require((rewardRates(i) * rewardsDuration * (num_periods_elapsed + 1)) <= ERC20(rewardTokens[i]).balanceOf(address(this)), string(abi.encodePacked("Not enough reward tokens available: ", rewardTokens[i])) );
}
// uint256 old_lastUpdateTime = lastUpdateTime;
// uint256 new_lastUpdateTime = block.timestamp;
// lastUpdateTime = periodFinish;
periodFinish = periodFinish + ((num_periods_elapsed + 1) * rewardsDuration);
// Update the rewards and time
_updateStoredRewardsAndTime();
// Update the fraxPerLPStored
fraxPerLPStored = fraxPerLPToken();
// Pull in rewards and set the reward rate for one week, based off of that
// If the stkAAVE rewards get messed up for some reason, set this to 0 and it will skip
if (rewardRatesManual[1] != 0) {
// Aave aFRAX
// ====================================
address[] memory the_assets = new address[](1);
the_assets[0] = 0xd4937682df3C8aEF4FE912A96A74121C0829E664; // aFRAX
uint256 stkaave_recd = IAaveIncentivesControllerPartial(0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5).claimRewards(
the_assets,
115792089237316195423570985008687907853269984665640564039457584007913129639935,
address(this)
);
rewardRatesManual[1] = stkaave_recd / rewardsDuration;
}
}
function _updateStoredRewardsAndTime() internal {
// Get the rewards
uint256[] memory rewards_per_token = rewardsPerToken();
// Update the rewardsPerTokenStored
for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){
rewardsPerTokenStored[i] = rewards_per_token[i];
}
// Update the last stored time
lastUpdateTime = lastTimeRewardApplicable();
}
function sync_gauge_weights(bool force_update) public {
// Loop through the gauge controllers
for (uint256 i = 0; i < gaugeControllers.length; i++){
address gauge_controller_address = gaugeControllers[i];
if (gauge_controller_address != address(0)) {
if (force_update || (block.timestamp > last_gauge_time_totals[i])){
// Update the gauge_relative_weight
last_gauge_relative_weights[i] = IFraxGaugeController(gauge_controller_address).gauge_relative_weight_write(address(this), block.timestamp);
last_gauge_time_totals[i] = IFraxGaugeController(gauge_controller_address).time_total();
}
}
}
}
function sync() public {
// Sync the gauge weight, if applicable
sync_gauge_weights(false);
// Update the fraxPerLPStored
fraxPerLPStored = fraxPerLPToken();
if (block.timestamp >= periodFinish) {
retroCatchUp();
}
else {
_updateStoredRewardsAndTime();
}
}
/* ========== RESTRICTED FUNCTIONS - Curator / migrator callable ========== */
// ------ FARM SYNCING ------
// In children...
// ------ PAUSES ------
function setPauses(
bool _stakingPaused,
bool _withdrawalsPaused,
bool _rewardsCollectionPaused
) external onlyByOwnGov {
stakingPaused = _stakingPaused;
withdrawalsPaused = _withdrawalsPaused;
rewardsCollectionPaused = _rewardsCollectionPaused;
}
/* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */
function unlockStakes() external onlyByOwnGov {
stakesUnlocked = !stakesUnlocked;
}
function toggleMigrations() external onlyByOwnGov {
migrationsOn = !migrationsOn;
}
// Adds supported migrator address
function toggleMigrator(address migrator_address) external onlyByOwnGov {
valid_migrators[migrator_address] = !valid_migrators[migrator_address];
}
// Adds a valid veFXS proxy address
function toggleValidVeFXSProxy(address _proxy_addr) external onlyByOwnGov {
valid_vefxs_proxies[_proxy_addr] = !valid_vefxs_proxies[_proxy_addr];
}
// Added to support recovering LP Rewards and other mistaken tokens from other systems to be distributed to holders
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) {
// Check if the desired token is a reward token
bool isRewardToken = false;
for (uint256 i = 0; i < rewardTokens.length; i++){
if (rewardTokens[i] == tokenAddress) {
isRewardToken = true;
break;
}
}
// Only the reward managers can take back their reward tokens
// Also, other tokens, like the staking token, airdrops, or accidental deposits, can be withdrawn by the owner
if (
(isRewardToken && rewardManagers[tokenAddress] == msg.sender)
|| (!isRewardToken && (msg.sender == owner))
) {
TransferHelper.safeTransfer(tokenAddress, msg.sender, tokenAmount);
return;
}
// If none of the above conditions are true
else {
revert("No valid tokens to recover");
}
}
function setMiscVariables(
uint256[6] memory _misc_vars
// [0]: uint256 _lock_max_multiplier,
// [1] uint256 _vefxs_max_multiplier,
// [2] uint256 _vefxs_per_frax_for_max_boost,
// [3] uint256 _vefxs_boost_scale_factor,
// [4] uint256 _lock_time_for_max_multiplier,
// [5] uint256 _lock_time_min
) external onlyByOwnGov {
require(_misc_vars[0] >= MULTIPLIER_PRECISION, "Must be >= MUL PREC");
require((_misc_vars[1] >= 0) && (_misc_vars[2] >= 0) && (_misc_vars[3] >= 0), "Must be >= 0");
require((_misc_vars[4] >= 1) && (_misc_vars[5] >= 1), "Must be >= 1");
lock_max_multiplier = _misc_vars[0];
vefxs_max_multiplier = _misc_vars[1];
vefxs_per_frax_for_max_boost = _misc_vars[2];
vefxs_boost_scale_factor = _misc_vars[3];
lock_time_for_max_multiplier = _misc_vars[4];
lock_time_min = _misc_vars[5];
}
// The owner or the reward token managers can set reward rates
function setRewardVars(address reward_token_address, uint256 _new_rate, address _gauge_controller_address, address _rewards_distributor_address) external onlyTknMgrs(reward_token_address) {
rewardRatesManual[rewardTokenAddrToIdx[reward_token_address]] = _new_rate;
gaugeControllers[rewardTokenAddrToIdx[reward_token_address]] = _gauge_controller_address;
rewardDistributors[rewardTokenAddrToIdx[reward_token_address]] = _rewards_distributor_address;
}
// The owner or the reward token managers can change managers
function changeTokenManager(address reward_token_address, address new_manager_address) external onlyTknMgrs(reward_token_address) {
rewardManagers[reward_token_address] = new_manager_address;
}
/* ========== A CHICKEN ========== */
//
// ,~.
// ,-'__ `-,
// {,-' `. } ,')
// ,( a ) `-.__ ,',')~,
// <=.) ( `-.__,==' ' ' '}
// ( ) /)
// `-'\ , )
// | \ `~. /
// \ `._ \ /
// \ `._____,' ,'
// `-. ,'
// `-._ _,-'
// 77jj'
// //_||
// __//--'/`
// ,--'/` '
//
// [hjw] https://textart.io/art/vw6Sa3iwqIRGkZsN1BC2vweF/chicken
}
// File contracts/Misc_AMOs/Lending_AMOs/aave/IScaledBalanceToken.sol
interface IScaledBalanceToken {
/**
* @dev Returns the scaled balance of the user. The scaled balance is the sum of all the
* updated stored balance divided by the reserve's liquidity index at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
**/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @dev Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled balance and the scaled total supply
**/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
* @return The scaled total supply
**/
function scaledTotalSupply() external view returns (uint256);
}
// File contracts/Misc_AMOs/Lending_AMOs/aave/IAToken.sol
interface IAToken is IERC20, IScaledBalanceToken {
function ATOKEN_REVISION() external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function EIP712_REVISION() external view returns (bytes memory);
function PERMIT_TYPEHASH() external view returns (bytes32);
function POOL() external view returns (address);
function RESERVE_TREASURY_ADDRESS() external view returns (address);
function UINT_MAX_VALUE() external view returns (uint256);
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
/**
* @dev Emitted after the mint action
* @param from The address performing the mint
* @param value The amount being
* @param index The new liquidity index of the reserve
**/
event Mint(address indexed from, uint256 value, uint256 index);
/**
* @dev Mints `amount` aTokens to `user`
* @param user The address receiving the minted tokens
* @param amount The amount of tokens getting minted
* @param index The new liquidity index of the reserve
* @return `true` if the the previous balance of the user was 0
*/
function mint(
address user,
uint256 amount,
uint256 index
) external returns (bool);
/**
* @dev Emitted after aTokens are burned
* @param from The owner of the aTokens, getting them burned
* @param target The address that will receive the underlying
* @param value The amount being burned
* @param index The new liquidity index of the reserve
**/
event Burn(address indexed from, address indexed target, uint256 value, uint256 index);
/**
* @dev Emitted during the transfer action
* @param from The user whose tokens are being transferred
* @param to The recipient
* @param value The amount being transferred
* @param index The new liquidity index of the reserve
**/
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
/**
* @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
* @param user The owner of the aTokens, getting them burned
* @param receiverOfUnderlying The address that will receive the underlying
* @param amount The amount being burned
* @param index The new liquidity index of the reserve
**/
function burn(
address user,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external;
/**
* @dev Mints aTokens to the reserve treasury
* @param amount The amount of tokens getting minted
* @param index The new liquidity index of the reserve
*/
function mintToTreasury(uint256 amount, uint256 index) external;
/**
* @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
* @param from The address getting liquidated, current owner of the aTokens
* @param to The recipient
* @param value The amount of tokens getting transferred
**/
function transferOnLiquidation(
address from,
address to,
uint256 value
) external;
/**
* @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer
* assets in borrow(), withdraw() and flashLoan()
* @param user The recipient of the aTokens
* @param amount The amount getting transferred
* @return The amount transferred
**/
function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);
}
// File contracts/Misc_AMOs/Lending_AMOs/aave/ILendingPool.sol
interface ILendingPool {
function FLASHLOAN_PREMIUM_TOTAL ( ) external view returns ( uint256 );
function LENDINGPOOL_REVISION ( ) external view returns ( uint256 );
function MAX_NUMBER_RESERVES ( ) external view returns ( uint256 );
function MAX_STABLE_RATE_BORROW_SIZE_PERCENT ( ) external view returns ( uint256 );
function borrow ( address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf ) external;
function deposit ( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external;
function finalizeTransfer ( address asset, address from, address to, uint256 amount, uint256 balanceFromBefore, uint256 balanceToBefore ) external;
function flashLoan ( address receiverAddress, address[] memory assets, uint256[] memory amounts, uint256[] memory modes, address onBehalfOf, bytes memory params, uint16 referralCode ) external;
function getAddressesProvider ( ) external view returns ( address );
// function getConfiguration ( address asset ) external view returns ( tuple );
// function getReserveData ( address asset ) external view returns ( tuple );
function getReserveNormalizedIncome ( address asset ) external view returns ( uint256 );
function getReserveNormalizedVariableDebt ( address asset ) external view returns ( uint256 );
function getReservesList ( ) external view returns ( address[] memory );
function getUserAccountData ( address user ) external view returns ( uint256 totalCollateralETH, uint256 totalDebtETH, uint256 availableBorrowsETH, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor );
// function getUserConfiguration ( address user ) external view returns ( tuple );
function initReserve ( address asset, address aTokenAddress, address stableDebtAddress, address variableDebtAddress, address interestRateStrategyAddress ) external;
function initialize ( address provider ) external;
function liquidationCall ( address collateralAsset, address debtAsset, address user, uint256 debtToCover, bool receiveAToken ) external;
function paused ( ) external view returns ( bool );
function rebalanceStableBorrowRate ( address asset, address user ) external;
function repay ( address asset, uint256 amount, uint256 rateMode, address onBehalfOf ) external returns ( uint256 );
function setConfiguration ( address asset, uint256 configuration ) external;
function setPause ( bool val ) external;
function setReserveInterestRateStrategyAddress ( address asset, address rateStrategyAddress ) external;
function setUserUseReserveAsCollateral ( address asset, bool useAsCollateral ) external;
function swapBorrowRateMode ( address asset, uint256 rateMode ) external;
function withdraw ( address asset, uint256 amount, address to ) external returns ( uint256 );
}
// File contracts/Staking/FraxUnifiedFarm_PosRebase.sol
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ===================== FraxUnifiedFarm_PosRebase ====================
// ====================================================================
// For positive rebase ERC20 Tokens like Aave's aToken and Compound's cToken
// Uses FraxUnifiedFarmTemplate.sol
// -------------------- VARIES --------------------
// Aave V2
// ------------------------------------------------
contract FraxUnifiedFarm_PosRebase is FraxUnifiedFarmTemplate {
/* ========== STATE VARIABLES ========== */
// -------------------- VARIES --------------------
// Aave V2
IAToken public stakingToken;
// Need to store this when the user stakes. If they lockAdditional, the base value needs to accrue and the
// Stored liquidity index needs to be updated
// https://docs.aave.com/developers/v/2.0/the-core-protocol/atokens#scaledbalanceof
mapping(bytes32 => uint256) public storedStkLiqIdx; // kek_id -> liquidity index.
// ------------------------------------------------
// 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 --------------------
// Aave V2
stakingToken = IAToken(_stakingToken);
}
/* ============= VIEWS ============= */
// ------ FRAX RELATED ------
function fraxPerLPToken() public view override returns (uint256) {
// Get the amount of FRAX 'inside' of the lp tokens
uint256 frax_per_lp_token;
// Aave V2
// ============================================
{
// Always 1-to-1, for simplicity. Autocompounding is handled by _accrueInterest
// Users can accrue up their principal by calling lockAdditional with 0 amount.
// Also will accrue at withdrawal time
frax_per_lp_token = 1e18;
}
return frax_per_lp_token;
}
// ------ LIQUIDITY AND WEIGHTS ------
// 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) {
// This is only called for the first stake to make sure the veFXS multiplier is not cut in half
midpoint_vefxs_multiplier = new_vefxs_multiplier;
}
else {
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];
uint256 lock_multiplier = thisStake.lock_multiplier;
// 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 - lastRewardClaimTime[account];
uint256 time_after_expiry = block.timestamp - thisStake.ending_timestamp;
// Get the weighted-average lock_multiplier
uint256 numerator = (lock_multiplier * time_before_expiry) + (MULTIPLIER_PRECISION * time_after_expiry);
lock_multiplier = numerator / (time_before_expiry + time_after_expiry);
}
// Otherwise, it needs to just be 1x
else {
lock_multiplier = MULTIPLIER_PRECISION;
}
}
uint256 liquidity = thisStake.liquidity;
uint256 combined_boosted_amount = (liquidity * (lock_multiplier + midpoint_vefxs_multiplier)) / MULTIPLIER_PRECISION;
new_combined_weight = new_combined_weight + combined_boosted_amount;
}
}
// ------ REBASE RELATED ------
// Aave V2
// ============================================
// Get currentLiquidityIndex from AAVE
function currLiqIdx() public view returns (uint256) {
return ILendingPool(stakingToken.POOL()).getReserveNormalizedIncome(frax_address);
}
// ------ LOCK RELATED ------
// All the locked stakes for a given account
function lockedStakesOf(address account) external view returns (LockedStake[] memory) {
return lockedStakes[account];
}
// Returns the length of the locked stakes for a given account
function lockedStakesOfLength(address account) external view returns (uint256) {
return lockedStakes[account].length;
}
// // All the locked stakes for a given account [old-school method]
// function lockedStakesOfMultiArr(address account) external view returns (
// bytes32[] memory kek_ids,
// uint256[] memory start_timestamps,
// uint256[] memory liquidities,
// uint256[] memory ending_timestamps,
// uint256[] memory lock_multipliers
// ) {
// for (uint256 i = 0; i < lockedStakes[account].length; i++){
// LockedStake memory thisStake = lockedStakes[account][i];
// kek_ids[i] = thisStake.kek_id;
// start_timestamps[i] = thisStake.start_timestamp;
// liquidities[i] = thisStake.liquidity;
// ending_timestamps[i] = thisStake.ending_timestamp;
// lock_multipliers[i] = thisStake.lock_multiplier;
// }
// }
/* =============== MUTATIVE FUNCTIONS =============== */
// ------ STAKING ------
function _getStake(address staker_address, bytes32 kek_id) internal view returns (LockedStake memory locked_stake, uint256 arr_idx) {
for (uint256 i = 0; i < lockedStakes[staker_address].length; i++){
if (kek_id == lockedStakes[staker_address][i].kek_id){
locked_stake = lockedStakes[staker_address][i];
arr_idx = i;
break;
}
}
require(locked_stake.kek_id == kek_id, "Stake not found");
}
// Add additional LPs to an existing locked stake
// REBASE: If you simply want to accrue interest, call this with addl_liq = 0
function lockAdditional(bytes32 kek_id, uint256 addl_liq) updateRewardAndBalance(msg.sender, true) public {
// Get the stake and its index
(LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id);
// Accrue the interest and get the updated stake
(thisStake, ) = _accrueInterest(msg.sender, thisStake, theArrayIndex);
// Return early if only accruing, to save gas
if (addl_liq == 0) return;
// Calculate the new amount
uint256 new_amt = thisStake.liquidity + addl_liq;
// Checks
require(addl_liq >= 0, "Must be positive");
// Pull the tokens from the sender
TransferHelper.safeTransferFrom(address(stakingToken), msg.sender, address(this), addl_liq);
// Update the stake
lockedStakes[msg.sender][theArrayIndex] = LockedStake(
kek_id,
thisStake.start_timestamp,
new_amt,
thisStake.ending_timestamp,
thisStake.lock_multiplier
);
// Update liquidities
_total_liquidity_locked += addl_liq;
_locked_liquidity[msg.sender] += addl_liq;
{
address the_proxy = getProxyFor(msg.sender);
if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += addl_liq;
}
// Need to call to update the combined weights
_updateRewardAndBalance(msg.sender, false);
}
// Two different stake functions are needed because of delegateCall and msg.sender issues (important for migration)
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 updateRewardAndBalance(staker_address, true) returns (bytes32) {
require(stakingPaused == false || valid_migrators[msg.sender] == true, "Staking paused or in migration");
require(secs >= lock_time_min, "Minimum stake time not met");
require(secs <= lock_time_for_max_multiplier,"Trying to lock for too long");
// Pull in the required token(s)
// Varies per farm
TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity);
// Get the lock multiplier and kek_id
uint256 lock_multiplier = lockMultiplier(secs);
bytes32 kek_id = keccak256(abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address]));
// Create the locked stake
lockedStakes[staker_address].push(LockedStake(
kek_id,
start_timestamp,
liquidity,
start_timestamp + secs,
lock_multiplier
));
// Store the liquidity index. Used later to give back principal + accrued interest
storedStkLiqIdx[kek_id] = currLiqIdx();
// Update liquidities
_total_liquidity_locked += liquidity;
_locked_liquidity[staker_address] += liquidity;
{
address the_proxy = getProxyFor(staker_address);
if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += liquidity;
}
// Need to call again to make sure everything is correct
_updateRewardAndBalance(staker_address, false);
emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address);
return kek_id;
}
// ------ WITHDRAWING ------
// Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues (important for migration)
function withdrawLocked(bytes32 kek_id, address destination_address) nonReentrant external returns (uint256) {
require(withdrawalsPaused == false, "Withdrawals paused");
return _withdrawLocked(msg.sender, destination_address, kek_id);
}
// No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper
// functions like migrator_withdraw_locked() and withdrawLocked()
function _withdrawLocked(
address staker_address,
address destination_address,
bytes32 kek_id
) internal returns (uint256) {
// Collect rewards first and then update the balances
_getReward(staker_address, destination_address, true);
// Get the stake and its index
(LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(staker_address, kek_id);
// Accrue the interest and get the updated stake
(thisStake, ) = _accrueInterest(staker_address, thisStake, theArrayIndex);
// Do safety checks
require(block.timestamp >= thisStake.ending_timestamp || stakesUnlocked == true || valid_migrators[msg.sender] == true, "Stake is still locked!");
uint256 liquidity = thisStake.liquidity;
if (liquidity > 0) {
// Update liquidities
_total_liquidity_locked -= liquidity;
_locked_liquidity[staker_address] -= liquidity;
{
address the_proxy = getProxyFor(staker_address);
if (the_proxy != address(0)) proxy_lp_balances[the_proxy] -= liquidity;
}
// Remove the stake from the array
delete lockedStakes[staker_address][theArrayIndex];
// Give the tokens to the destination_address
// Should throw if insufficient balance
stakingToken.transfer(destination_address, liquidity);
// Need to call again to make sure everything is correct
_updateRewardAndBalance(staker_address, false);
// REBASE: leave liquidity in the event tracking alone, not giveBackAmt
emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address);
}
return liquidity;
}
// REBASE SPECIFIC
// Catches-up the user's accrued interest and sets it as the new principal (liquidity)
function _accrueInterest(
address staker_address,
LockedStake memory thisStake,
uint256 theArrayIndex
) internal returns (LockedStake memory, uint256) {
// Calculate the new liquidity as well as the diff
// new pricipal = (old principal ∗ currentLiquidityIndex) / (old liquidity index)
uint256 new_liq = (thisStake.liquidity * currLiqIdx()) / storedStkLiqIdx[thisStake.kek_id];
uint256 liq_diff = new_liq - thisStake.liquidity;
// Update the new principal
lockedStakes[staker_address][theArrayIndex].liquidity = new_liq;
// Update the liquidity totals
_total_liquidity_locked += liq_diff;
_locked_liquidity[staker_address] += liq_diff;
{
address the_proxy = getProxyFor(staker_address);
if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += liq_diff;
}
// Store the new liquidity index. Used later to give back principal + accrued interest
storedStkLiqIdx[thisStake.kek_id] = currLiqIdx();
return (lockedStakes[staker_address][theArrayIndex], theArrayIndex);
}
function _getRewardExtraLogic(address rewardee, address destination_address) internal override {
// Do nothing
}
/* ========== RESTRICTED FUNCTIONS - Curator / migrator callable ========== */
// Migrator can stake for someone else (they won't be able to withdraw it back though, only staker_address can).
function migrator_stakeLocked_for(address staker_address, uint256 amount, uint256 secs, uint256 start_timestamp) external isMigrating {
require(staker_allowed_migrators[staker_address][msg.sender] && valid_migrators[msg.sender], "Mig. invalid or unapproved");
_stakeLocked(staker_address, msg.sender, amount, secs, start_timestamp);
}
// Used for migrations
function migrator_withdraw_locked(address staker_address, bytes32 kek_id) external isMigrating {
require(staker_allowed_migrators[staker_address][msg.sender] && valid_migrators[msg.sender], "Mig. invalid or unapproved");
_withdrawLocked(staker_address, msg.sender, kek_id);
}
/* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */
// Inherited...
/* ========== EVENTS ========== */
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/Staking/Variants/FraxUnifiedFarm_PosRebase_aFRAX.sol
contract FraxUnifiedFarm_PosRebase_aFRAX is FraxUnifiedFarm_PosRebase {
constructor (
address _owner,
address[] memory _rewardTokens,
address[] memory _rewardManagers,
uint256[] memory _rewardRates,
address[] memory _gaugeControllers,
address[] memory _rewardDistributors,
address _stakingToken
)
FraxUnifiedFarm_PosRebase(_owner , _rewardTokens, _rewardManagers, _rewardRates, _gaugeControllers, _rewardDistributors, _stakingToken)
{}
}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":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":"uint256","name":"secs","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"source_address","type":"address"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"WithdrawLocked","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"calcCurCombinedWeight","outputs":[{"internalType":"uint256","name":"old_combined_weight","type":"uint256"},{"internalType":"uint256","name":"new_vefxs_multiplier","type":"uint256"},{"internalType":"uint256","name":"new_combined_weight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"address","name":"new_manager_address","type":"address"}],"name":"changeTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"combinedWeightOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currLiqIdx","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":"fraxPerLPStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":[],"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":"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_PosRebase.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":"staker_address","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"secs","type":"uint256"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"}],"name":"migrator_stakeLocked_for","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"},{"internalType":"bytes32","name":"kek_id","type":"bytes32"}],"name":"migrator_withdraw_locked","outputs":[],"stateMutability":"nonpayable","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"}],"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":"migrator_address","type":"address"}],"name":"stakerToggleMigrator","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 IAToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedStkLiqIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"toggleMigrations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_address","type":"address"}],"name":"toggleMigrator","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":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"address","name":"destination_address","type":"address"}],"name":"withdrawLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052600380546001600160a01b03191673c8418af6358ffdda74e09ca9cc3fe03ca6adc5b01790556729a2241af62c00006007556305a39a8060085562015180600955673782dace9d900000600a55671bc16d674ec80000600b819055600c553480156200006f57600080fd5b5060405162005abc38038062005abc8339810160408190526200009291620005ae565b86868686868686868686868686856001600160a01b038116620000fb5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600160025584516200016d90601190602088019062000385565b5081516200018390601290602085019062000385565b5080516200019990601390602084019062000385565b508251620001af906014906020860190620003ef565b5060005b85518110156200031a578060156000888481518110620001d757620001d7620006b5565b6020908102919091018101516001600160a01b03168252810191909152604001600090812091909155601680546001810182559082527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901558451859082908110620002475762000247620006b5565b602002602001015160106000888481518110620002685762000268620006b5565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601a805460018181019092557f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01829055601b8054918201815582527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc10155806200031181620006e1565b915050620001b3565b506024805460ff191690554260068190556200033b9062093a8090620006fd565b6005555050602480546001600160a01b039096166501000000000002600160281b600160c81b03199096169590951790945550620007189f50505050505050505050505050505050565b828054828255906000526020600020908101928215620003dd579160200282015b82811115620003dd57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620003a6565b50620003eb9291506200042d565b5090565b828054828255906000526020600020908101928215620003dd579160200282015b82811115620003dd57825182559160200191906001019062000410565b5b80821115620003eb57600081556001016200042e565b80516001600160a01b03811681146200045c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620004a257620004a262000461565b604052919050565b60006001600160401b03821115620004c657620004c662000461565b5060051b60200190565b600082601f830112620004e257600080fd5b81516020620004fb620004f583620004aa565b62000477565b82815260059290921b840181019181810190868411156200051b57600080fd5b8286015b848110156200054157620005338162000444565b83529183019183016200051f565b509695505050505050565b600082601f8301126200055e57600080fd5b8151602062000571620004f583620004aa565b82815260059290921b840181019181810190868411156200059157600080fd5b8286015b8481101562000541578051835291830191830162000595565b600080600080600080600060e0888a031215620005ca57600080fd5b620005d58862000444565b60208901519097506001600160401b0380821115620005f357600080fd5b620006018b838c01620004d0565b975060408a01519150808211156200061857600080fd5b620006268b838c01620004d0565b965060608a01519150808211156200063d57600080fd5b6200064b8b838c016200054c565b955060808a01519150808211156200066257600080fd5b620006708b838c01620004d0565b945060a08a01519150808211156200068757600080fd5b50620006968a828b01620004d0565b925050620006a760c0890162000444565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620006f657620006f6620006cb565b5060010190565b60008219821115620007135762000713620006cb565b500190565b61539480620007286000396000f3fe608060405234801561001057600080fd5b50600436106104205760003560e01c80638da5cb5b11610235578063d42fc9b411610135578063e7f30582116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109d1578063facefb64146109e4578063fff6cae9146109f757600080fd5b8063f2a8d349146109b5578063f2caeb1e146109be57600080fd5b8063e7f305821461097d578063eb3c209e14610990578063ebe2b12b146109a3578063f288baf6146109ac57600080fd5b8063de1a655111610104578063de1a655114610947578063e01f62bf1461095a578063e1ba95d214610962578063e44b9fa51461096a57600080fd5b8063d42fc9b4146108d8578063d5e1a9c6146108eb578063d7400d56146108fe578063d9f96e8d1461091157600080fd5b8063b94c4dcb116101c8578063c8f33c9111610197578063cc2abd641161017c578063cc2abd64146108b3578063cdc82e80146108c6578063d2010fb4146108cf57600080fd5b8063c8f33c9114610874578063ca6df29d1461087d57600080fd5b8063b94c4dcb14610825578063b9ec92231461082e578063c00007b01461084e578063c35438261461086157600080fd5b8063a2217bc511610204578063a2217bc5146107ee578063aa1d4fce146107f6578063affaa7a4146107ff578063b85efd061461081257600080fd5b80638da5cb5b1461079b57806391cf600a146107bb5780639637927f146107ce578063a0f23476146107db57600080fd5b8063387edc861161034057806370641a36116102d357806379ba5097116102a25780637f472e54116102875780637f472e54146107475780638980f11f1461075a5780638bad86a71461076d57600080fd5b806379ba5097146107205780637d6ef08e1461072857600080fd5b806370641a36146106a157806372f702f3146106a95780637910d17b146106d25780637970833e146106e557600080fd5b80635bfd92581161030f5780635bfd92581461066257806364f2c0601461067057806369339245146106785780636e27cef91461069857600080fd5b8063387edc86146105e657806341a16f3f146105f95780634fd2b5361461062f57806353a47bb71461064257600080fd5b8063215951e2116103b85780632c0c2a0a116103875780632c0c2a0a146105805780633650aff21461059357806336f89af2146105a6578063386a9525146105dc57600080fd5b8063215951e2146104e7578063231b68dc146104ef57806328408bab1461051257806328ef934e1461056d57600080fd5b806317b18c89116103f457806317b18c89146104995780631c1f78eb146104ac5780631e090f01146104b45780631face856146104d457600080fd5b80628cc262146104255780630d7bac4f1461044e57806312edb24c1461046f5780631627540c14610484575b600080fd5b610438610433366004614cd4565b6109ff565b6040516104459190614cf1565b60405180910390f35b61046161045c366004614d35565b610b7e565b604051908152602001610445565b610477610bce565b6040516104459190614d9f565b610497610492366004614cd4565b610c3d565b005b6104616104a7366004614db2565b610d62565b610438610dec565b6104c76104c2366004614cd4565b610e8d565b6040516104459190614dd4565b6104616104e2366004614cd4565b610f41565b610461610f86565b6105026104fd366004614e42565b6110c2565b6040519015158152602001610445565b610548610520366004614cd4565b60236020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610445565b61049761057b366004614e7b565b611130565b61046161058e366004614cd4565b611270565b6104976105a1366004614cd4565b61154e565b6104616105b4366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61046162093a8081565b6104976105f4366004614cd4565b611641565b610548610607366004614cd4565b60106020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61046161063d366004614cd4565b61172c565b6001546105489073ffffffffffffffffffffffffffffffffffffffff1681565b670de0b6b3a7640000610461565b601d54610461565b610461610686366004614cd4565b60156020526000908152604090205481565b61046160095481565b61043861174d565b6024546105489065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104386106e0366004614ec4565b6118ac565b6106f86106f3366004614ef2565b611928565b604080519586526020860194909452928401919091526060830152608082015260a001610445565b610497611976565b610461610736366004614cd4565b602080526000908152604090205481565b610461610755366004614cd4565b611ac1565b610497610768366004614ef2565b611ad8565b61078061077b366004614cd4565b611cc1565b60408051938452602084019290925290820152606001610445565b6000546105489073ffffffffffffffffffffffffffffffffffffffff1681565b6104976107c9366004614cd4565b611f8f565b6024546105029060ff1681565b6104616107e9366004614cd4565b612082565b61049761213d565b610461600a5481565b61049761080d366004614cd4565b612216565b610497610820366004614db2565b612306565b61046160085481565b61046161083c366004614d35565b60256020526000908152604090205481565b61043861085c366004614cd4565b6124cd565b61054861086f366004614cd4565b612555565b61046160065481565b61046161088b366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff1660009081526026602052604090205490565b6104976108c1366004614f1e565b6125b3565b61046160075481565b61046160045481565b6104616108e6366004614cd4565b6126ec565b6104976108f9366004614f69565b612728565b61049761090c366004614cd4565b612917565b61046161091f366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b610497610955366004614e42565b612abc565b601c54610461565b610497612ba3565b610461610978366004614fbc565b612c74565b61049761098b366004614cd4565b612d63565b61049761099e366004614ef2565b612ebd565b61046160055481565b610461600b5481565b610461600c5481565b6104616109cc366004614d35565b612ff4565b6104976109df366004614fe1565b61310b565b6104976109f236600461502d565b6132e1565b6104976134a1565b60606000610a0b61174d565b60115490915067ffffffffffffffff811115610a2957610a29614ffe565b604051908082528060200260200182016040528015610a52578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610b785760005b601154811015610b765773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610af157610af16150d2565b6020026020010151610b039190615130565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b339190615147565b610b3d9190615184565b610b4791906151bf565b838281518110610b5957610b596150d2565b602090810291909101015280610b6e816151d7565b915050610a84565b505b50919050565b600754600854600091610bc891610b9d670de0b6b3a764000083615130565b610ba79086615147565b610bb19190615184565b610bc390670de0b6b3a76400006151bf565b6134d2565b92915050565b60606011805480602002602001604051908101604052809291908181526020018280548015610c3357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c08575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ce9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b60028055610de033808585426134ea565b60016002559392505050565b60145460609067ffffffffffffffff811115610e0a57610e0a614ffe565b604051908082528060200260200182016040528015610e33578160200160208202803683370190505b50905060005b601454811015610e895762093a80610e5082612ff4565b610e5a9190615147565b828281518110610e6c57610e6c6150d2565b602090810291909101015280610e81816151d7565b915050610e39565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602660209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f3657838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610ed2565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600454670de0b6b3a764000091610f7c91615147565b610bc89190615184565b6000602460059054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637535d2466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611019919061520f565b6040517fd15e005300000000000000000000000000000000000000000000000000000000815273853d955acef822db058eb8505911ed77f175b99e600482015273ffffffffffffffffffffffffffffffffffffffff919091169063d15e005390602401602060405180830381865afa158015611099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bd919061522c565b905090565b6000805473ffffffffffffffffffffffffffffffffffffffff908116908416036110ee57506001610bc8565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526010602052604090205481851691160361112757506001610bc8565b50600092915050565b60245460ff6101009091041615156001146111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260226020908152604080832033845290915290205460ff1680156111f657503360009081526021602052604090205460ff165b61125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610ce0565b61126984338585856134ea565b5050505050565b6000808061127d84612555565b905073ffffffffffffffffffffffffffffffffffffffff811615611334576003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152909116906370a0823190602401602060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132f919061522c565b6113c8565b6003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152909116906370a0823190602401602060405180830381865afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c8919061522c565b91506000670de0b6b3a7640000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611466919061522c565b6114709190615147565b600a54600b546114809086615147565b61148a9190615147565b6114949190615184565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156114c3576114be84611ac1565b6114cc565b6114cc8761172c565b9050801561151e576000816114e9670de0b6b3a764000088615147565b6114f39190615184565b9050670de0b6b3a7640000600b548261150c9190615147565b6115169190615184565b925050611523565b600091505b508082116115315780611533565b815b9450600b5485111561154557600b5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806115875750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6115ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60028054036116ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b600280556024546301000000900460ff1615611724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ce0565b506001600255565b6000670de0b6b3a7640000600c54611743846126ec565b610f7c9190615147565b6060601c54600014806117605750601d54155b156117ba576016805480602002602001604051908101604052809291908181526020018280548015610c3357602002820191906000526020600020905b81548152602001906001019080831161179d575050505050905090565b60115467ffffffffffffffff8111156117d5576117d5614ffe565b6040519080825280602002602001820160405280156117fe578160200160208202803683370190505b50905060005b601654811015610e8957601d5461181a82612ff4565b60065461182561392a565b61182f9190615130565b6118399190615147565b61184b90670de0b6b3a7640000615147565b6118559190615184565b60168281548110611868576118686150d2565b906000526020600020015461187d91906151bf565b82828151811061188f5761188f6150d2565b6020908102919091010152806118a4816151d7565b915050611804565b60606002805403611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b60028055610de0338484613938565b6026602052816000526040600020818154811061194457600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610ce0565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600c5461174384610f41565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611b055750611b0533826110c2565b611b6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b6000805b601154811015611be5578473ffffffffffffffffffffffffffffffffffffffff1660118281548110611ba357611ba36150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611bd35760019150611be5565b80611bdd816151d7565b915050611b6f565b50808015611c19575073ffffffffffffffffffffffffffffffffffffffff8481166000908152601060205260409020541633145b80611c44575080158015611c44575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611c5a57611c54843385613b5c565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610ce0565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080611cf284611270565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e602052604081205491935090158015611d4c575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b15611d58575081611d98565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d6020526040902054600290611d8b90856151bf565b611d959190615184565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff8616600090815260266020526040902054811015611f865773ffffffffffffffffffffffffffffffffffffffff86166000908152602660205260408120805483908110611e0357611e036150d2565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060008160800151905042826060015111611f3357606082015173ffffffffffffffffffffffffffffffffffffffff89166000908152601960205260409020541015611f285773ffffffffffffffffffffffffffffffffffffffff88166000908152601960205260408120546060840151611eca9190615130565b90506000836060015142611ede9190615130565b90506000611ef482670de0b6b3a7640000615147565b611efe8486615147565b611f0891906151bf565b9050611f1482846151bf565b611f1e9082615184565b9350505050611f33565b50670de0b6b3a76400005b60408201516000670de0b6b3a7640000611f4d87856151bf565b611f579084615147565b611f619190615184565b9050611f6d81886151bf565b9650505050508080611f7e906151d7565b915050611d9f565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611fc85750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61202e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff166000908152600e6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600454600c546120949190615147565b6003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152670de0b6b3a76400009283929116906370a0823190602401602060405180830381865afa15801561210f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612133919061522c565b6117439190615147565b60005473ffffffffffffffffffffffffffffffffffffffff163314806121765750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6121dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526021602052604090205460ff166122a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206d69677261746f72206164647265737300000000000000006044820152606401610ce0565b33600090815260226020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292905220805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055565b3360016123138282613cc5565b6000806123203387613de7565b9150915061232f338383613fac565b5091506000859003612342575050611c54565b600085836040015161235491906151bf565b90506024546123849065010000000000900473ffffffffffffffffffffffffffffffffffffffff163330896141dc565b6040805160a0810182528881526020858101518183015281830184905260608087015190830152608080870151908301523360009081526026909152919091208054849081106123d6576123d66150d2565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601c600082825461242b91906151bf565b9091555050336000908152601e60205260408120805488929061244f9084906151bf565b909155506000905061246033612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156124b85773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548992906124b29084906151bf565b90915550505b506124c4336000613cc5565b50505050505050565b6060600280540361253a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b6002805561254a33836001613938565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e602052604081205460ff1615612587575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602360205260409020541690565b60005473ffffffffffffffffffffffffffffffffffffffff163314806125ec5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480549115156301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff93151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff95151564010000000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ffff909316929092179390931791909116179055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600454670de0b6b3a764000091610f7c91615147565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612755575061275533826110c2565b6127bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601560205260409020546014805486929081106127f6576127f66150d2565b9060005260206000200181905550826012601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612857576128576150d2565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9485161790559187168152601590915260409020546013805484929081106128c8576128c86150d2565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e602052604090205460ff166129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f6020908152604080832033845290915290205460ff16612a40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610ce0565b33600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155601e8352818420549084529180528220805491929091612ab49084906151bf565b909155505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612ae95750612ae933826110c2565b612b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b5073ffffffffffffffffffffffffffffffffffffffff918216600090815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480612bdc5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403612ce1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b6002805560245462010000900460ff1615612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610ce0565b610de033838561437a565b336000908152600e602052604090205460ff16612ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ce0565b336000818152600f6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603612eba5773ffffffffffffffffffffffffffffffffffffffff8116600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e8252808320543384529180528220805491929091612ab4908490615130565b50565b60245460ff610100909104161515600114612f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260226020908152604080832033845290915290205460ff168015612f8357503360009081526021602052604090205460ff165b612fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610ce0565b611cbc82338361437a565b6000806012838154811061300a5761300a6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156130e557670de0b6b3a7640000601a8481548110613050576130506150d2565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ca919061522c565b6130d49190615147565b6130de9190615184565b9150610b78565b601483815481106130f8576130f86150d2565b9060005260206000200154915050919050565b60005b6012548110156132dd5760006012828154811061312d5761312d6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156132ca57828061317f5750601b8281548110613171576131716150d2565b906000526020600020015442115b156132ca576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af11580156131f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321a919061522c565b601a838154811061322d5761322d6150d2565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132aa919061522c565b601b83815481106132bd576132bd6150d2565b6000918252602090912001555b50806132d5816151d7565b91505061310e565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061331a5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613380576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b8051670de0b6b3a764000011156133f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610ce0565b608081015160011180159061340d575060a0810151600111155b613473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610ce0565b80516007556020810151600b556040810151600c556060810151600a55608081015160085560a00151600955565b6134ab600061310b565b670de0b6b3a764000060045560055442106134ca576134c861468a565b565b6134c8614b3f565b60008183106134e157816134e3565b825b9392505050565b60008560016134f98282613cc5565b602454640100000000900460ff16158061352757503360009081526021602052604090205460ff1615156001145b61358d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5374616b696e6720706175736564206f7220696e206d6967726174696f6e00006044820152606401610ce0565b6009548510156135f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ce0565b600854851115613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ce0565b6024546136939065010000000000900473ffffffffffffffffffffffffffffffffffffffff168830896141dc565b600061369e86610b7e565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526026835283902060a0850184528185529184018a90529183018b905290925090606081016137918a8a6151bf565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151928101929092556040810151600283015560608101516003830155608001516004909101556137e9610f86565b600082815260256020526040812091909155601c80548a929061380d9084906151bf565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601e6020526040812080548a92906138479084906151bf565b90915550600090506138588b612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156138b05773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548b92906138aa9084906151bf565b90915550505b506138bc8a6000613cc5565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006110bd426005546134d2565b60608360016139478282613cc5565b6024546301000000900460ff16156139bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ce0565b60115467ffffffffffffffff8111156139d6576139d6614ffe565b6040519080825280602002602001820160405280156139ff578160200160208202803683370190505b50925060005b601154811015613b295773ffffffffffffffffffffffffffffffffffffffff871660009081526018602090815260408083208484529091529020548451859083908110613a5457613a546150d2565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526018825260408082208483529092529081208190558451859083908110613aa857613aa86150d2565b60200260200101511115613b1757613b1760118281548110613acc57613acc6150d2565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613b0a57613b0a6150d2565b6020026020010151613b5c565b80613b21816151d7565b915050613a05565b50505073ffffffffffffffffffffffffffffffffffffffff90931660009081526019602052604090204290555090919050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613bf39190615271565b6000604051808303816000865af19150503d8060008114613c30576040519150601f19603f3d011682016040523d82523d6000602084013e613c35565b606091505b5091509150818015613c5f575080511580613c5f575080806020019051810190613c5f919061528d565b611269576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610ce0565b8015613cd357613cd36134a1565b73ffffffffffffffffffffffffffffffffffffffff8216156132dd576000806000613cfd85611cc1565b925092509250613d0c85614bb2565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260409020829055828110613d90576000613d478483615130565b905080601d54613d5791906151bf565b601d55613d6481856151bf565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f602052604090205550611269565b6000613d9c8285615130565b905080601d54613dac9190615130565b601d55613db98185615130565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902055505050505050565b613e1c6040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff8516600090815260266020526040902054811015613f3a5773ffffffffffffffffffffffffffffffffffffffff85166000908152602660205260409020805482908110613e8457613e846150d2565b9060005260206000209060050201600001548403613f285773ffffffffffffffffffffffffffffffffffffffff85166000908152602660205260409020805482908110613ed357613ed36150d2565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150613f3a565b80613f32816151d7565b915050613e20565b5081518314613fa5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610ce0565b9250929050565b613fe16040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b82516000908152602560205260408120548190613ffc610f86565b866040015161400b9190615147565b6140159190615184565b905060008560400151826140299190615130565b73ffffffffffffffffffffffffffffffffffffffff881660009081526026602052604090208054919250839187908110614065576140656150d2565b90600052602060002090600502016002018190555080601c600082825461408c91906151bf565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040812080548392906140c69084906151bf565b90915550600090506140d788612555565b905073ffffffffffffffffffffffffffffffffffffffff81161561412f5773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548492906141299084906151bf565b90915550505b50614138610f86565b865160009081526025602090815260408083209390935573ffffffffffffffffffffffffffffffffffffffff8a168252602690522080548690811061417f5761417f6150d2565b906000526020600020906005020185816040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509150935093505050935093915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161427b9190615271565b6000604051808303816000865af19150503d80600081146142b8576040519150601f19603f3d011682016040523d82523d6000602084013e6142bd565b606091505b50915091508180156142e75750805115806142e75750808060200190518101906142e7919061528d565b614372576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610ce0565b505050505050565b600061438884846001613938565b506000806143968685613de7565b915091506143a5868383613fac565b506060810151909250421015806143c3575060245460ff1615156001145b806143e257503360009081526021602052604090205460ff1615156001145b614448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610ce0565b604082015180156146805780601c60008282546144659190615130565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601e60205260408120805483929061449f908490615130565b90915550600090506144b088612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156145085773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054849290614502908490615130565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff87166000908152602660205260409020805483908110614540576145406150d2565b60009182526020822060059190910201818155600181018290556002810182905560038101829055600490810191909155602480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116948201949094529182018490526501000000000090049091169063a9059cbb906044016020604051808303816000875af11580156145f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614619919061528d565b50614625876000613cc5565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b60135481101561477b576000601382815481106146ac576146ac6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614768576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614741573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061476591906152aa565b50505b5080614773816151d7565b91505061468d565b50600062093a80600554426147909190615130565b61479a9190615184565b905060005b60115481101561497d57601181815481106147bc576147bc6150d2565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614833573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614857919061522c565b6148628360016151bf565b62093a8061486f84612ff4565b6148799190615147565b6148839190615147565b111560118281548110614898576148986150d2565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660448201526058016040516020818303038152906040529061496a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce091906152ce565b5080614975816151d7565b91505061479f565b5062093a8061498d8260016151bf565b6149979190615147565b6005546149a491906151bf565b6005556149af614b3f565b670de0b6b3a76400006004556014805460019081106149d0576149d06150d2565b9060005260206000200154600014612eba576040805160018082528183019092526000916020808301908036833701905050905073d4937682df3c8aef4fe912a96a74121c0829e66481600081518110614a2c57614a2c6150d2565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040517f3111e7b300000000000000000000000000000000000000000000000000000000815260009073d784927ff2f95ba542bfc824c8a8a98f3495f6b590633111e7b390614ac89085907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90309060040161531f565b6020604051808303816000875af1158015614ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b0b919061522c565b9050614b1a62093a8082615184565b6014600181548110614b2e57614b2e6150d2565b600091825260209091200155505050565b6000614b4961174d565b905060005b601654811015614ba357818181518110614b6a57614b6a6150d2565b602002602001015160168281548110614b8557614b856150d2565b60009182526020909120015580614b9b816151d7565b915050614b4e565b50614bac61392a565b60065550565b73ffffffffffffffffffffffffffffffffffffffff811615612eba576000614bd9826109ff565b905060005b8151811015614c4757818181518110614bf957614bf96150d2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601883526040808220858352909352919091205580614c3f816151d7565b915050614bde565b5060005b8151811015611cbc5760168181548110614c6757614c676150d2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260178252604080842085855290925291205580614caa816151d7565b915050614c4b565b73ffffffffffffffffffffffffffffffffffffffff81168114612eba57600080fd5b600060208284031215614ce657600080fd5b81356134e381614cb2565b6020808252825182820181905260009190848201906040850190845b81811015614d2957835183529284019291840191600101614d0d565b50909695505050505050565b600060208284031215614d4757600080fd5b5035919050565b600081518084526020808501945080840160005b83811015614d9457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614d62565b509495945050505050565b6020815260006134e36020830184614d4e565b60008060408385031215614dc557600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e355781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614df1565b5091979650505050505050565b60008060408385031215614e5557600080fd5b8235614e6081614cb2565b91506020830135614e7081614cb2565b809150509250929050565b60008060008060808587031215614e9157600080fd5b8435614e9c81614cb2565b966020860135965060408601359560600135945092505050565b8015158114612eba57600080fd5b60008060408385031215614ed757600080fd5b8235614ee281614cb2565b91506020830135614e7081614eb6565b60008060408385031215614f0557600080fd5b8235614f1081614cb2565b946020939093013593505050565b600080600060608486031215614f3357600080fd5b8335614f3e81614eb6565b92506020840135614f4e81614eb6565b91506040840135614f5e81614eb6565b809150509250925092565b60008060008060808587031215614f7f57600080fd5b8435614f8a81614cb2565b9350602085013592506040850135614fa181614cb2565b91506060850135614fb181614cb2565b939692955090935050565b60008060408385031215614fcf57600080fd5b823591506020830135614e7081614cb2565b600060208284031215614ff357600080fd5b81356134e381614eb6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561503f57600080fd5b82601f83011261504e57600080fd5b60405160c0810181811067ffffffffffffffff82111715615098577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c08401858111156150ad57600080fd5b845b818110156150c75780358352602092830192016150af565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561514257615142615101565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561517f5761517f615101565b500290565b6000826151ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082198211156151d2576151d2615101565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361520857615208615101565b5060010190565b60006020828403121561522157600080fd5b81516134e381614cb2565b60006020828403121561523e57600080fd5b5051919050565b60005b83811015615260578181015183820152602001615248565b83811115611c545750506000910152565b60008251615283818460208701615245565b9190910192915050565b60006020828403121561529f57600080fd5b81516134e381614eb6565b600080604083850312156152bd57600080fd5b505080516020909101519092909150565b60208152600082518060208401526152ed816040850160208701615245565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6060815260006153326060830186614d4e565b905083602083015273ffffffffffffffffffffffffffffffffffffffff8316604083015294935050505056fea264697066735822122062234020a79da5894696814a693b51a31d672a6e51f17fa40d3cc3868dc56bea64736f6c634300080d0033000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000d4937682df3c8aef4fe912a96a74121c0829e66400000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000a86cc92e3da00000000000000000000000000000000000000000000000000000002b1de5ada0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd340000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104205760003560e01c80638da5cb5b11610235578063d42fc9b411610135578063e7f30582116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109d1578063facefb64146109e4578063fff6cae9146109f757600080fd5b8063f2a8d349146109b5578063f2caeb1e146109be57600080fd5b8063e7f305821461097d578063eb3c209e14610990578063ebe2b12b146109a3578063f288baf6146109ac57600080fd5b8063de1a655111610104578063de1a655114610947578063e01f62bf1461095a578063e1ba95d214610962578063e44b9fa51461096a57600080fd5b8063d42fc9b4146108d8578063d5e1a9c6146108eb578063d7400d56146108fe578063d9f96e8d1461091157600080fd5b8063b94c4dcb116101c8578063c8f33c9111610197578063cc2abd641161017c578063cc2abd64146108b3578063cdc82e80146108c6578063d2010fb4146108cf57600080fd5b8063c8f33c9114610874578063ca6df29d1461087d57600080fd5b8063b94c4dcb14610825578063b9ec92231461082e578063c00007b01461084e578063c35438261461086157600080fd5b8063a2217bc511610204578063a2217bc5146107ee578063aa1d4fce146107f6578063affaa7a4146107ff578063b85efd061461081257600080fd5b80638da5cb5b1461079b57806391cf600a146107bb5780639637927f146107ce578063a0f23476146107db57600080fd5b8063387edc861161034057806370641a36116102d357806379ba5097116102a25780637f472e54116102875780637f472e54146107475780638980f11f1461075a5780638bad86a71461076d57600080fd5b806379ba5097146107205780637d6ef08e1461072857600080fd5b806370641a36146106a157806372f702f3146106a95780637910d17b146106d25780637970833e146106e557600080fd5b80635bfd92581161030f5780635bfd92581461066257806364f2c0601461067057806369339245146106785780636e27cef91461069857600080fd5b8063387edc86146105e657806341a16f3f146105f95780634fd2b5361461062f57806353a47bb71461064257600080fd5b8063215951e2116103b85780632c0c2a0a116103875780632c0c2a0a146105805780633650aff21461059357806336f89af2146105a6578063386a9525146105dc57600080fd5b8063215951e2146104e7578063231b68dc146104ef57806328408bab1461051257806328ef934e1461056d57600080fd5b806317b18c89116103f457806317b18c89146104995780631c1f78eb146104ac5780631e090f01146104b45780631face856146104d457600080fd5b80628cc262146104255780630d7bac4f1461044e57806312edb24c1461046f5780631627540c14610484575b600080fd5b610438610433366004614cd4565b6109ff565b6040516104459190614cf1565b60405180910390f35b61046161045c366004614d35565b610b7e565b604051908152602001610445565b610477610bce565b6040516104459190614d9f565b610497610492366004614cd4565b610c3d565b005b6104616104a7366004614db2565b610d62565b610438610dec565b6104c76104c2366004614cd4565b610e8d565b6040516104459190614dd4565b6104616104e2366004614cd4565b610f41565b610461610f86565b6105026104fd366004614e42565b6110c2565b6040519015158152602001610445565b610548610520366004614cd4565b60236020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610445565b61049761057b366004614e7b565b611130565b61046161058e366004614cd4565b611270565b6104976105a1366004614cd4565b61154e565b6104616105b4366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61046162093a8081565b6104976105f4366004614cd4565b611641565b610548610607366004614cd4565b60106020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61046161063d366004614cd4565b61172c565b6001546105489073ffffffffffffffffffffffffffffffffffffffff1681565b670de0b6b3a7640000610461565b601d54610461565b610461610686366004614cd4565b60156020526000908152604090205481565b61046160095481565b61043861174d565b6024546105489065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104386106e0366004614ec4565b6118ac565b6106f86106f3366004614ef2565b611928565b604080519586526020860194909452928401919091526060830152608082015260a001610445565b610497611976565b610461610736366004614cd4565b602080526000908152604090205481565b610461610755366004614cd4565b611ac1565b610497610768366004614ef2565b611ad8565b61078061077b366004614cd4565b611cc1565b60408051938452602084019290925290820152606001610445565b6000546105489073ffffffffffffffffffffffffffffffffffffffff1681565b6104976107c9366004614cd4565b611f8f565b6024546105029060ff1681565b6104616107e9366004614cd4565b612082565b61049761213d565b610461600a5481565b61049761080d366004614cd4565b612216565b610497610820366004614db2565b612306565b61046160085481565b61046161083c366004614d35565b60256020526000908152604090205481565b61043861085c366004614cd4565b6124cd565b61054861086f366004614cd4565b612555565b61046160065481565b61046161088b366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff1660009081526026602052604090205490565b6104976108c1366004614f1e565b6125b3565b61046160075481565b61046160045481565b6104616108e6366004614cd4565b6126ec565b6104976108f9366004614f69565b612728565b61049761090c366004614cd4565b612917565b61046161091f366004614cd4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b610497610955366004614e42565b612abc565b601c54610461565b610497612ba3565b610461610978366004614fbc565b612c74565b61049761098b366004614cd4565b612d63565b61049761099e366004614ef2565b612ebd565b61046160055481565b610461600b5481565b610461600c5481565b6104616109cc366004614d35565b612ff4565b6104976109df366004614fe1565b61310b565b6104976109f236600461502d565b6132e1565b6104976134a1565b60606000610a0b61174d565b60115490915067ffffffffffffffff811115610a2957610a29614ffe565b604051908082528060200260200182016040528015610a52578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610b785760005b601154811015610b765773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610af157610af16150d2565b6020026020010151610b039190615130565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b339190615147565b610b3d9190615184565b610b4791906151bf565b838281518110610b5957610b596150d2565b602090810291909101015280610b6e816151d7565b915050610a84565b505b50919050565b600754600854600091610bc891610b9d670de0b6b3a764000083615130565b610ba79086615147565b610bb19190615184565b610bc390670de0b6b3a76400006151bf565b6134d2565b92915050565b60606011805480602002602001604051908101604052809291908181526020018280548015610c3357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c08575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ce9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b60028055610de033808585426134ea565b60016002559392505050565b60145460609067ffffffffffffffff811115610e0a57610e0a614ffe565b604051908082528060200260200182016040528015610e33578160200160208202803683370190505b50905060005b601454811015610e895762093a80610e5082612ff4565b610e5a9190615147565b828281518110610e6c57610e6c6150d2565b602090810291909101015280610e81816151d7565b915050610e39565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602660209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f3657838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610ed2565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600454670de0b6b3a764000091610f7c91615147565b610bc89190615184565b6000602460059054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637535d2466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611019919061520f565b6040517fd15e005300000000000000000000000000000000000000000000000000000000815273853d955acef822db058eb8505911ed77f175b99e600482015273ffffffffffffffffffffffffffffffffffffffff919091169063d15e005390602401602060405180830381865afa158015611099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bd919061522c565b905090565b6000805473ffffffffffffffffffffffffffffffffffffffff908116908416036110ee57506001610bc8565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526010602052604090205481851691160361112757506001610bc8565b50600092915050565b60245460ff6101009091041615156001146111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260226020908152604080832033845290915290205460ff1680156111f657503360009081526021602052604090205460ff165b61125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610ce0565b61126984338585856134ea565b5050505050565b6000808061127d84612555565b905073ffffffffffffffffffffffffffffffffffffffff811615611334576003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152909116906370a0823190602401602060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132f919061522c565b6113c8565b6003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152909116906370a0823190602401602060405180830381865afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c8919061522c565b91506000670de0b6b3a7640000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611466919061522c565b6114709190615147565b600a54600b546114809086615147565b61148a9190615147565b6114949190615184565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156114c3576114be84611ac1565b6114cc565b6114cc8761172c565b9050801561151e576000816114e9670de0b6b3a764000088615147565b6114f39190615184565b9050670de0b6b3a7640000600b548261150c9190615147565b6115169190615184565b925050611523565b600091505b508082116115315780611533565b815b9450600b5485111561154557600b5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806115875750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6115ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60028054036116ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b600280556024546301000000900460ff1615611724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ce0565b506001600255565b6000670de0b6b3a7640000600c54611743846126ec565b610f7c9190615147565b6060601c54600014806117605750601d54155b156117ba576016805480602002602001604051908101604052809291908181526020018280548015610c3357602002820191906000526020600020905b81548152602001906001019080831161179d575050505050905090565b60115467ffffffffffffffff8111156117d5576117d5614ffe565b6040519080825280602002602001820160405280156117fe578160200160208202803683370190505b50905060005b601654811015610e8957601d5461181a82612ff4565b60065461182561392a565b61182f9190615130565b6118399190615147565b61184b90670de0b6b3a7640000615147565b6118559190615184565b60168281548110611868576118686150d2565b906000526020600020015461187d91906151bf565b82828151811061188f5761188f6150d2565b6020908102919091010152806118a4816151d7565b915050611804565b60606002805403611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b60028055610de0338484613938565b6026602052816000526040600020818154811061194457600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610ce0565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600c5461174384610f41565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611b055750611b0533826110c2565b611b6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b6000805b601154811015611be5578473ffffffffffffffffffffffffffffffffffffffff1660118281548110611ba357611ba36150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611bd35760019150611be5565b80611bdd816151d7565b915050611b6f565b50808015611c19575073ffffffffffffffffffffffffffffffffffffffff8481166000908152601060205260409020541633145b80611c44575080158015611c44575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611c5a57611c54843385613b5c565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610ce0565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080611cf284611270565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e602052604081205491935090158015611d4c575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b15611d58575081611d98565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d6020526040902054600290611d8b90856151bf565b611d959190615184565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff8616600090815260266020526040902054811015611f865773ffffffffffffffffffffffffffffffffffffffff86166000908152602660205260408120805483908110611e0357611e036150d2565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060008160800151905042826060015111611f3357606082015173ffffffffffffffffffffffffffffffffffffffff89166000908152601960205260409020541015611f285773ffffffffffffffffffffffffffffffffffffffff88166000908152601960205260408120546060840151611eca9190615130565b90506000836060015142611ede9190615130565b90506000611ef482670de0b6b3a7640000615147565b611efe8486615147565b611f0891906151bf565b9050611f1482846151bf565b611f1e9082615184565b9350505050611f33565b50670de0b6b3a76400005b60408201516000670de0b6b3a7640000611f4d87856151bf565b611f579084615147565b611f619190615184565b9050611f6d81886151bf565b9650505050508080611f7e906151d7565b915050611d9f565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611fc85750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b61202e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff166000908152600e6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600454600c546120949190615147565b6003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152670de0b6b3a76400009283929116906370a0823190602401602060405180830381865afa15801561210f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612133919061522c565b6117439190615147565b60005473ffffffffffffffffffffffffffffffffffffffff163314806121765750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6121dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526021602052604090205460ff166122a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206d69677261746f72206164647265737300000000000000006044820152606401610ce0565b33600090815260226020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292905220805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055565b3360016123138282613cc5565b6000806123203387613de7565b9150915061232f338383613fac565b5091506000859003612342575050611c54565b600085836040015161235491906151bf565b90506024546123849065010000000000900473ffffffffffffffffffffffffffffffffffffffff163330896141dc565b6040805160a0810182528881526020858101518183015281830184905260608087015190830152608080870151908301523360009081526026909152919091208054849081106123d6576123d66150d2565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601c600082825461242b91906151bf565b9091555050336000908152601e60205260408120805488929061244f9084906151bf565b909155506000905061246033612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156124b85773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548992906124b29084906151bf565b90915550505b506124c4336000613cc5565b50505050505050565b6060600280540361253a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b6002805561254a33836001613938565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e602052604081205460ff1615612587575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602360205260409020541690565b60005473ffffffffffffffffffffffffffffffffffffffff163314806125ec5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480549115156301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff93151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff95151564010000000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ffff909316929092179390931791909116179055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600454670de0b6b3a764000091610f7c91615147565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612755575061275533826110c2565b6127bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601560205260409020546014805486929081106127f6576127f66150d2565b9060005260206000200181905550826012601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612857576128576150d2565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9485161790559187168152601590915260409020546013805484929081106128c8576128c86150d2565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e602052604090205460ff166129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f6020908152604080832033845290915290205460ff16612a40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610ce0565b33600090815260236020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155601e8352818420549084529180528220805491929091612ab49084906151bf565b909155505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612ae95750612ae933826110c2565b612b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610ce0565b5073ffffffffffffffffffffffffffffffffffffffff918216600090815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480612bdc5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403612ce1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce0565b6002805560245462010000900460ff1615612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610ce0565b610de033838561437a565b336000908152600e602052604090205460ff16612ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610ce0565b336000818152600f6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790556023909252909120541603612eba5773ffffffffffffffffffffffffffffffffffffffff8116600090815260236020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e8252808320543384529180528220805491929091612ab4908490615130565b50565b60245460ff610100909104161515600114612f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610ce0565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260226020908152604080832033845290915290205460ff168015612f8357503360009081526021602052604090205460ff165b612fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610ce0565b611cbc82338361437a565b6000806012838154811061300a5761300a6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156130e557670de0b6b3a7640000601a8481548110613050576130506150d2565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ca919061522c565b6130d49190615147565b6130de9190615184565b9150610b78565b601483815481106130f8576130f86150d2565b9060005260206000200154915050919050565b60005b6012548110156132dd5760006012828154811061312d5761312d6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156132ca57828061317f5750601b8281548110613171576131716150d2565b906000526020600020015442115b156132ca576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af11580156131f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321a919061522c565b601a838154811061322d5761322d6150d2565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132aa919061522c565b601b83815481106132bd576132bd6150d2565b6000918252602090912001555b50806132d5816151d7565b91505061310e565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061331a5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b613380576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610ce0565b8051670de0b6b3a764000011156133f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610ce0565b608081015160011180159061340d575060a0810151600111155b613473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610ce0565b80516007556020810151600b556040810151600c556060810151600a55608081015160085560a00151600955565b6134ab600061310b565b670de0b6b3a764000060045560055442106134ca576134c861468a565b565b6134c8614b3f565b60008183106134e157816134e3565b825b9392505050565b60008560016134f98282613cc5565b602454640100000000900460ff16158061352757503360009081526021602052604090205460ff1615156001145b61358d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5374616b696e6720706175736564206f7220696e206d6967726174696f6e00006044820152606401610ce0565b6009548510156135f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610ce0565b600854851115613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610ce0565b6024546136939065010000000000900473ffffffffffffffffffffffffffffffffffffffff168830896141dc565b600061369e86610b7e565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526026835283902060a0850184528185529184018a90529183018b905290925090606081016137918a8a6151bf565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151928101929092556040810151600283015560608101516003830155608001516004909101556137e9610f86565b600082815260256020526040812091909155601c80548a929061380d9084906151bf565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601e6020526040812080548a92906138479084906151bf565b90915550600090506138588b612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156138b05773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548b92906138aa9084906151bf565b90915550505b506138bc8a6000613cc5565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006110bd426005546134d2565b60608360016139478282613cc5565b6024546301000000900460ff16156139bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610ce0565b60115467ffffffffffffffff8111156139d6576139d6614ffe565b6040519080825280602002602001820160405280156139ff578160200160208202803683370190505b50925060005b601154811015613b295773ffffffffffffffffffffffffffffffffffffffff871660009081526018602090815260408083208484529091529020548451859083908110613a5457613a546150d2565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526018825260408082208483529092529081208190558451859083908110613aa857613aa86150d2565b60200260200101511115613b1757613b1760118281548110613acc57613acc6150d2565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613b0a57613b0a6150d2565b6020026020010151613b5c565b80613b21816151d7565b915050613a05565b50505073ffffffffffffffffffffffffffffffffffffffff90931660009081526019602052604090204290555090919050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613bf39190615271565b6000604051808303816000865af19150503d8060008114613c30576040519150601f19603f3d011682016040523d82523d6000602084013e613c35565b606091505b5091509150818015613c5f575080511580613c5f575080806020019051810190613c5f919061528d565b611269576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610ce0565b8015613cd357613cd36134a1565b73ffffffffffffffffffffffffffffffffffffffff8216156132dd576000806000613cfd85611cc1565b925092509250613d0c85614bb2565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260409020829055828110613d90576000613d478483615130565b905080601d54613d5791906151bf565b601d55613d6481856151bf565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f602052604090205550611269565b6000613d9c8285615130565b905080601d54613dac9190615130565b601d55613db98185615130565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902055505050505050565b613e1c6040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff8516600090815260266020526040902054811015613f3a5773ffffffffffffffffffffffffffffffffffffffff85166000908152602660205260409020805482908110613e8457613e846150d2565b9060005260206000209060050201600001548403613f285773ffffffffffffffffffffffffffffffffffffffff85166000908152602660205260409020805482908110613ed357613ed36150d2565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509250809150613f3a565b80613f32816151d7565b915050613e20565b5081518314613fa5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610ce0565b9250929050565b613fe16040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b82516000908152602560205260408120548190613ffc610f86565b866040015161400b9190615147565b6140159190615184565b905060008560400151826140299190615130565b73ffffffffffffffffffffffffffffffffffffffff881660009081526026602052604090208054919250839187908110614065576140656150d2565b90600052602060002090600502016002018190555080601c600082825461408c91906151bf565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040812080548392906140c69084906151bf565b90915550600090506140d788612555565b905073ffffffffffffffffffffffffffffffffffffffff81161561412f5773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548492906141299084906151bf565b90915550505b50614138610f86565b865160009081526025602090815260408083209390935573ffffffffffffffffffffffffffffffffffffffff8a168252602690522080548690811061417f5761417f6150d2565b906000526020600020906005020185816040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509150935093505050935093915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161427b9190615271565b6000604051808303816000865af19150503d80600081146142b8576040519150601f19603f3d011682016040523d82523d6000602084013e6142bd565b606091505b50915091508180156142e75750805115806142e75750808060200190518101906142e7919061528d565b614372576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610ce0565b505050505050565b600061438884846001613938565b506000806143968685613de7565b915091506143a5868383613fac565b506060810151909250421015806143c3575060245460ff1615156001145b806143e257503360009081526021602052604090205460ff1615156001145b614448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610ce0565b604082015180156146805780601c60008282546144659190615130565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601e60205260408120805483929061449f908490615130565b90915550600090506144b088612555565b905073ffffffffffffffffffffffffffffffffffffffff8116156145085773ffffffffffffffffffffffffffffffffffffffff8116600090815260208052604081208054849290614502908490615130565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff87166000908152602660205260409020805483908110614540576145406150d2565b60009182526020822060059190910201818155600181018290556002810182905560038101829055600490810191909155602480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116948201949094529182018490526501000000000090049091169063a9059cbb906044016020604051808303816000875af11580156145f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614619919061528d565b50614625876000613cc5565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b60135481101561477b576000601382815481106146ac576146ac6150d2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614768576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614741573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061476591906152aa565b50505b5080614773816151d7565b91505061468d565b50600062093a80600554426147909190615130565b61479a9190615184565b905060005b60115481101561497d57601181815481106147bc576147bc6150d2565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614833573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614857919061522c565b6148628360016151bf565b62093a8061486f84612ff4565b6148799190615147565b6148839190615147565b111560118281548110614898576148986150d2565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660448201526058016040516020818303038152906040529061496a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce091906152ce565b5080614975816151d7565b91505061479f565b5062093a8061498d8260016151bf565b6149979190615147565b6005546149a491906151bf565b6005556149af614b3f565b670de0b6b3a76400006004556014805460019081106149d0576149d06150d2565b9060005260206000200154600014612eba576040805160018082528183019092526000916020808301908036833701905050905073d4937682df3c8aef4fe912a96a74121c0829e66481600081518110614a2c57614a2c6150d2565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040517f3111e7b300000000000000000000000000000000000000000000000000000000815260009073d784927ff2f95ba542bfc824c8a8a98f3495f6b590633111e7b390614ac89085907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90309060040161531f565b6020604051808303816000875af1158015614ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b0b919061522c565b9050614b1a62093a8082615184565b6014600181548110614b2e57614b2e6150d2565b600091825260209091200155505050565b6000614b4961174d565b905060005b601654811015614ba357818181518110614b6a57614b6a6150d2565b602002602001015160168281548110614b8557614b856150d2565b60009182526020909120015580614b9b816151d7565b915050614b4e565b50614bac61392a565b60065550565b73ffffffffffffffffffffffffffffffffffffffff811615612eba576000614bd9826109ff565b905060005b8151811015614c4757818181518110614bf957614bf96150d2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601883526040808220858352909352919091205580614c3f816151d7565b915050614bde565b5060005b8151811015611cbc5760168181548110614c6757614c676150d2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260178252604080842085855290925291205580614caa816151d7565b915050614c4b565b73ffffffffffffffffffffffffffffffffffffffff81168114612eba57600080fd5b600060208284031215614ce657600080fd5b81356134e381614cb2565b6020808252825182820181905260009190848201906040850190845b81811015614d2957835183529284019291840191600101614d0d565b50909695505050505050565b600060208284031215614d4757600080fd5b5035919050565b600081518084526020808501945080840160005b83811015614d9457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614d62565b509495945050505050565b6020815260006134e36020830184614d4e565b60008060408385031215614dc557600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e355781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614df1565b5091979650505050505050565b60008060408385031215614e5557600080fd5b8235614e6081614cb2565b91506020830135614e7081614cb2565b809150509250929050565b60008060008060808587031215614e9157600080fd5b8435614e9c81614cb2565b966020860135965060408601359560600135945092505050565b8015158114612eba57600080fd5b60008060408385031215614ed757600080fd5b8235614ee281614cb2565b91506020830135614e7081614eb6565b60008060408385031215614f0557600080fd5b8235614f1081614cb2565b946020939093013593505050565b600080600060608486031215614f3357600080fd5b8335614f3e81614eb6565b92506020840135614f4e81614eb6565b91506040840135614f5e81614eb6565b809150509250925092565b60008060008060808587031215614f7f57600080fd5b8435614f8a81614cb2565b9350602085013592506040850135614fa181614cb2565b91506060850135614fb181614cb2565b939692955090935050565b60008060408385031215614fcf57600080fd5b823591506020830135614e7081614cb2565b600060208284031215614ff357600080fd5b81356134e381614eb6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561503f57600080fd5b82601f83011261504e57600080fd5b60405160c0810181811067ffffffffffffffff82111715615098577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c08401858111156150ad57600080fd5b845b818110156150c75780358352602092830192016150af565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561514257615142615101565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561517f5761517f615101565b500290565b6000826151ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082198211156151d2576151d2615101565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361520857615208615101565b5060010190565b60006020828403121561522157600080fd5b81516134e381614cb2565b60006020828403121561523e57600080fd5b5051919050565b60005b83811015615260578181015183820152602001615248565b83811115611c545750506000910152565b60008251615283818460208701615245565b9190910192915050565b60006020828403121561529f57600080fd5b81516134e381614eb6565b600080604083850312156152bd57600080fd5b505080516020909101519092909150565b60208152600082518060208401526152ed816040850160208701615245565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6060815260006153326060830186614d4e565b905083602083015273ffffffffffffffffffffffffffffffffffffffff8316604083015294935050505056fea264697066735822122062234020a79da5894696814a693b51a31d672a6e51f17fa40d3cc3868dc56bea64736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000d4937682df3c8aef4fe912a96a74121c0829e66400000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000a86cc92e3da00000000000000000000000000000000000000000000000000000002b1de5ada0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd340000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0xfF5B4BCbf765FE363269114e1c765229a29eDeFD
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0x4da27a545c0c5B758a6BA100e3a049001de870f5
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27,0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [3] : _rewardRates (uint256[]): 11574074074074,11574074074
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34,0x0000000000000000000000000000000000000000
Arg [6] : _stakingToken (address): 0xd4937682df3C8aEF4FE912A96A74121C0829E664
-----Encoded View---------------
22 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [6] : 000000000000000000000000d4937682df3c8aef4fe912a96a74121c0829e664
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 0000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f5
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [11] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [12] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [14] : 00000000000000000000000000000000000000000000000000000a86cc92e3da
Arg [15] : 00000000000000000000000000000000000000000000000000000002b1de5ada
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [20] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
105245:523:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58847:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61057:313;;;;;;:::i;:::-;;:::i;:::-;;;1393:25:1;;;1381:2;1366:18;61057:313:0;1247:177:1;57126:109:0;;;:::i;:::-;;;;;;;:::i;46389:141::-;;;;;;:::i;:::-;;:::i;:::-;;97676:190;;;;;;:::i;:::-;;:::i;59440:339::-;;;:::i;94111:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;61589:179::-;;;;;;:::i;:::-;;:::i;93864:152::-;;;:::i;56790:298::-;;;;;;:::i;:::-;;:::i;:::-;;;4193:14:1;;4186:22;4168:41;;4156:2;4141:18;56790:298:0;4028:187:1;53929:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4396:42:1;4384:55;;;4366:74;;4354:2;4339:18;53929:60:0;4220:226:1;104086:357:0;;;;;;:::i;:::-;;:::i;63137:1752::-;;;;;;:::i;:::-;;:::i;76030:161::-;;;;;;:::i;:::-;;:::i;60493:127::-;;;;;;:::i;:::-;60586:26;;60559:7;60586:26;;;:17;:26;;;;;;;60493:127;52671:48;;52713:6;52671:48;;68933:238;;;;;;:::i;:::-;;:::i;52299:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;62289:181;;;;;;:::i;:::-;;:::i;46157:29::-;;;;;;;;;90421:587;90948:4;90421:587;;60207:111;60288:22;;60207:111;;52552:55;;;;;;:::i;:::-;;;;;;;;;;;;;;51578:36;;;;;;57950:681;;;:::i;88869:27::-;;;;;;;;;;;;69640:206;;;;;;:::i;:::-;;:::i;89329:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;6244:25:1;;;6300:2;6285:18;;6278:34;;;;6328:18;;;6321:34;;;;6386:2;6371:18;;6364:34;6429:3;6414:19;;6407:35;6231:3;6216:19;89329:53:0;5985:463:1;46538:271:0;;;:::i;53524:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;62478:199;;;;;;:::i;:::-;;:::i;76530:1013::-;;;;;;:::i;:::-;;:::i;91115:2589::-;;;;;;:::i;:::-;;:::i;:::-;;;;6655:25:1;;;6711:2;6696:18;;6689:34;;;;6739:18;;;6732:34;6643:2;6628:18;91115:2589:0;6453:319:1;46130:20:0;;;;;;;;;76240:161;;;;;;:::i;:::-;;:::i;54133:26::-;;;;;;;;;61871:224;;;;;;:::i;:::-;;:::i;75885:97::-;;;:::i;51667:55::-;;;;;;65033:278;;;;;;:::i;:::-;;:::i;96068:1479::-;;;;;;:::i;:::-;;:::i;51424:61::-;;;;;;89157:50;;;;;;:::i;:::-;;;;;;;;;;;;;;69460:172;;;;;;:::i;:::-;;:::i;62685:444::-;;;;;;:::i;:::-;;:::i;51270:29::-;;;;;;94320:133;;;;;;:::i;:::-;94417:21;;94390:7;94417:21;;;:12;:21;;;;;:28;;94320:133;75376:311;;;;;;:::i;:::-;;:::i;51350:50::-;;;;;;51073:30;;;;;;61415:166;;;;;;:::i;:::-;;:::i;78586:483::-;;;;;;:::i;:::-;;:::i;66179:419::-;;;;;;:::i;:::-;;:::i;60041:128::-;;;;;;:::i;:::-;60135:26;;60108:7;60135:26;;;:17;:26;;;;;;;60041:128;79144:207;;;;;;:::i;:::-;;:::i;59877:113::-;59959:23;;59877:113;;75780:97;;;:::i;100137:259::-;;;;;;:::i;:::-;;:::i;65479:610::-;;;;;;:::i;:::-;;:::i;104479:298::-;;;;;;:::i;:::-;;:::i;51236:27::-;;;;;;51805:51;;;;;;51881:59;;;;;;57428:452;;;;;;:::i;:::-;;:::i;74055:761::-;;;;;;:::i;:::-;;:::i;77551:958::-;;;;;;:::i;:::-;;:::i;74824:363::-;;;:::i;58847:529::-;58901:27;58941;58971:17;:15;:17::i;:::-;59026:12;:19;58941:47;;-1:-1:-1;59012:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59012:34:0;-1:-1:-1;59063:26:0;;;59092:1;59063:26;;;:17;:26;;;;;;58999:47;;-1:-1:-1;59063:30:0;59059:310;;59114:9;59109:249;59133:12;:19;59129:23;;59109:249;;;59323:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;59242:32;;;:23;:32;;;;;:35;;;;;;;;;59226:13;;59282:4;;59242:35;59226:10;;59340:1;;59226:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;59196:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;59195:91;;;;:::i;:::-;59194:148;;;;:::i;:::-;59178:10;59189:1;59178:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;59154:3;;;;:::i;:::-;;;;59109:249;;;;59059:310;58930:446;58847:529;;;:::o;61057:313::-;61166:19;;61307:28;;61116:7;;61143:218;;61260:42;51201:4;61166:19;61260:42;:::i;:::-;61252:51;;:4;:51;:::i;:::-;61251:84;;;;:::i;:::-;61200:150;;51201:4;61200:150;:::i;:::-;61143:8;:218::i;:::-;61136:225;61057:313;-1:-1:-1;;61057:313:0:o;57126:109::-;57179:16;57215:12;57208:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57126:109;:::o;46389:141::-;46869:5;;;;46855:10;:19;46847:79;;;;;;;11884:2:1;46847:79:0;;;11866:21:1;11923:2;11903:18;;;11896:30;11962:34;11942:18;;;11935:62;12033:17;12013:18;;;12006:45;12068:19;;46847:79:0;;;;;;;;;46461:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;46500:22:::1;::::0;4366:74:1;;;46500:22:0::1;::::0;4354:2:1;4339:18;46500:22:0::1;;;;;;;46389:141:::0;:::o;97676:190::-;97761:7;45064:1;45670:7;;:19;45662:63;;;;;;;12300:2:1;45662:63:0;;;12282:21:1;12339:2;12319:18;;;12312:30;12378:33;12358:18;;;12351:61;12429:18;;45662:63:0;12098:355:1;45662:63:0;45064:1;45803:18;;97788:70:::1;97801:10;::::0;97825:9;97836:4;97842:15:::1;97788:12;:70::i;:::-;45020:1:::0;45982:7;:22;97781:77;97676:190;-1:-1:-1;;;97676:190:0:o;59440:339::-;59590:17;:24;59495:41;;59576:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59576:39:0;;59549:66;;59633:9;59628:144;59652:17;:24;59648:28;;59628:144;;;52713:6;59728:14;59740:1;59728:11;:14::i;:::-;:32;;;;:::i;:::-;59698:24;59723:1;59698:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;59678:3;;;;:::i;:::-;;;;59628:144;;;;59440:339;:::o;94111:133::-;94215:21;;;;;;;:12;:21;;;;;;;;94208:28;;;;;;;;;;;;;;;;;94175:20;;94208:28;;94215:21;;94208:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94111:133;;;:::o;61589:179::-;61704:32;;;61658:7;61704:32;;;:17;:32;;;;;;61686:15;;51201:4;;61686:50;;;:::i;:::-;61685:75;;;;:::i;93864:152::-;93907:7;93947:12;;;;;;;;;;;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93934:74;;;;;50989:42;93934:74;;;4366::1;93934:60:0;;;;;;;;4339:18:1;;93934:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93927:81;;93864:152;:::o;56790:298::-;56886:4;56921:5;;;;;;56906:20;;;;56902:136;;-1:-1:-1;56935:4:0;56928:11;;56902:136;56977:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;56973:65;;-1:-1:-1;57034:4:0;57027:11;;56973:65;-1:-1:-1;57074:5:0;56790:298;;;;:::o;104086:357::-;55030:12;;;;;;;;:20;;:12;:20;55022:49;;;;;;;13105:2:1;55022:49:0;;;13087:21:1;13144:2;13124:18;;;13117:30;13183:18;13163;;;13156:46;13219:18;;55022:49:0;12903:340:1;55022:49:0;104239:40:::1;::::0;::::1;;::::0;;;:24:::1;:40;::::0;;;;;;;104280:10:::1;104239:52:::0;;;;;;;;::::1;;:83:::0;::::1;;;-1:-1:-1::0;104311:10:0::1;104295:27;::::0;;;:15:::1;:27;::::0;;;;;::::1;;104239:83;104231:122;;;::::0;::::1;::::0;;13450:2:1;104231:122:0::1;::::0;::::1;13432:21:1::0;13489:2;13469:18;;;13462:30;13528:28;13508:18;;;13501:56;13574:18;;104231:122:0::1;13248:350:1::0;104231:122:0::1;104364:71;104377:14;104393:10;104405:6;104413:4;104419:15;104364:12;:71::i;:::-;;104086:357:::0;;;;:::o;63137:1752::-;63200:24;;;63361:20;63373:7;63361:11;:20::i;:::-;63341:40;-1:-1:-1;63412:23:0;;;;63411:81;;63466:5;;:26;;;;;:5;4384:55:1;;;63466:26:0;;;4366:74:1;63466:5:0;;;;:15;;4339:18:1;;63466:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63411:81;;;63439:5;;:24;;;;;:5;4384:55:1;;;63439:24:0;;;4366:74:1;63439:5:0;;;;:15;;4339:18:1;;63439:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63392:100;;63598:19;51201:4;63722:5;;;;;;;;;;;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;63663:24;;63640:20;;63621:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;63620:145;;;;:::i;:::-;63598:167;-1:-1:-1;63874:19:0;;64089:23;;;;64088:94;;64147:35;64172:9;64147:24;:35::i;:::-;64088:94;;;64116:28;64136:7;64116:19;:28::i;:::-;64059:123;-1:-1:-1;64203:30:0;;64199:323;;64254:27;64328:26;64285:39;51201:4;64285:16;:39;:::i;:::-;64284:70;;;;:::i;:::-;64254:100;;51201:4;64428:20;;64406:19;:42;;;;:::i;:::-;64405:67;;;;:::i;:::-;64391:81;;64234:254;64199:323;;;64521:1;64507:15;;64199:323;63904:699;64690:11;64676;:25;:53;;64718:11;64676:53;;;64704:11;64676:53;64656:74;;64820:20;;64801:16;:39;64797:84;;;64861:20;;64842:39;;64797:84;63226:1663;;;;63137:1752;;;:::o;76030:161::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;76150:33:::1;;;::::0;;;:15:::1;:33;::::0;;;;;;76113:70;;::::1;76150:33;::::0;;::::1;76149:34;76113:70;::::0;;76030:161::o;68933:238::-;45064:1;45670:7;;:19;45662:63;;;;;;;12300:2:1;45662:63:0;;;12282:21:1;12339:2;12319:18;;;12312:30;12378:33;12358:18;;;12351:61;12429:18;;45662:63:0;12098:355:1;45662:63:0;45064:1;45803:18;;69030:23:::1;::::0;;;::::1;;;:32;69022:70;;;::::0;::::1;::::0;;14155:2:1;69022:70:0::1;::::0;::::1;14137:21:1::0;14194:2;14174:18;;;14167:30;14233:27;14213:18;;;14206:55;14278:18;;69022:70:0::1;13953:349:1::0;69022:70:0::1;-1:-1:-1::0;45020:1:0;45982:7;:22;68933:238::o;62289:181::-;62356:7;51201:4;62410:28;;62384:23;62399:7;62384:14;:23::i;:::-;:54;;;;:::i;57950:681::-;57998:41;58056:23;;58083:1;58056:28;:59;;;-1:-1:-1;58088:22:0;;:27;58056:59;58052:572;;;58139:21;58132:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57950:681;:::o;58052:572::-;58243:12;:19;58229:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58229:34:0;;58202:61;;58283:9;58278:289;58302:21;:28;58298:32;;58278:289;;;58510:22;;58485:14;58497:1;58485:11;:14::i;:::-;58467;;58438:26;:24;:26::i;:::-;:43;;;;:::i;:::-;58437:62;;;;:::i;:::-;:69;;58502:4;58437:69;:::i;:::-;58436:96;;;;:::i;:::-;58386:21;58408:1;58386:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;58356:24;58381:1;58356:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;58332:3;;;;:::i;:::-;;;;58278:289;;69640:206;69742:16;45064:1;45670:7;;:19;45662:63;;;;;;;12300:2:1;45662:63:0;;;12282:21:1;12339:2;12319:18;;;12312:30;12378:33;12358:18;;;12351:61;12429:18;;45662:63:0;12098:355:1;45662:63:0;45064:1;45803:18;;69778:60:::1;69789:10;69801:19:::0;69822:15;69778:10:::1;:60::i;89329:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89329:53:0;;-1:-1:-1;89329:53:0;;;:::o;46538:271::-;46607:14;;;;46593:10;:28;46585:94;;;;;;;14509:2:1;46585:94:0;;;14491:21:1;14548:2;14528:18;;;14521:30;14587:34;14567:18;;;14560:62;14658:23;14638:18;;;14631:51;14699:19;;46585:94:0;14307:417:1;46585:94:0;46708:5;;;46715:14;46695:35;;;46708:5;;;;14964:34:1;;46715:14:0;;;;15029:2:1;15014:18;;15007:43;46695:35:0;;14876:18:1;46695:35:0;;;;;;;46749:14;;;;46741:22;;;;;;46749:14;;;46741:22;;;;46774:27;;;46538:271::o;62478:199::-;62556:7;51201:4;62617:28;;62584:30;62600:13;62584:15;:30::i;76530:1013::-;54875:5;;76616:12;;54875:5;;54861:10;:19;;:74;;;54884:51;54902:10;54914:20;54884:17;:51::i;:::-;54853:107;;;;;;;15263:2:1;54853:107:0;;;15245:21:1;15302:2;15282:18;;;15275:30;15341:22;15321:18;;;15314:50;15381:18;;54853:107:0;15061:344:1;54853:107:0;76698:18:::1;76740:9:::0;76735:192:::1;76759:12;:19:::0;76755:23;::::1;76735:192;;;76823:12;76804:31;;:12;76817:1;76804:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:31:::0;76800:116:::1;;76872:4;76856:20;;76895:5;;76800:116;76780:3:::0;::::1;::::0;::::1;:::i;:::-;;;;76735:192;;;;77153:13;:59;;;;-1:-1:-1::0;77170:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;77202:10;77170:42;77153:59;77152:123;;;;77236:13;77235:14;:39;;;;-1:-1:-1::0;77268:5:0::1;::::0;::::1;;77254:10;:19;77235:39;77130:406;;;77306:66;77334:12;77348:10;77360:11;77306:27;:66::i;:::-;77387:7;76530:1013:::0;;;:::o;77130:406::-:1;77488:36;::::0;::::1;::::0;;15612:2:1;77488:36:0::1;::::0;::::1;15594:21:1::0;15651:2;15631:18;;;15624:30;15690:28;15670:18;;;15663:56;15736:18;;77488:36:0::1;15410:350:1::0;54971:1:0::1;76530:1013:::0;;;:::o;91115:2589::-;91418:26;;;91216:27;91418:26;;;:17;:26;;;;;;;91216:27;91605:24;91436:7;91605:15;:24::i;:::-;91690:26;;;91642:33;91690:26;;;:17;:26;;;;;;91582:47;;-1:-1:-1;91642:33:0;91690:31;:66;;;;-1:-1:-1;91725:26:0;;;;;;;:17;:26;;;;;;:31;91690:66;91686:386;;;-1:-1:-1;91910:20:0;91686:386;;;92024:31;;;;;;;:22;:31;;;;;;92059:1;;92001:54;;:20;:54;:::i;:::-;92000:60;;;;:::i;:::-;91972:88;;91686:386;92207:1;92185:23;;92224:9;92219:1478;92243:21;;;;;;;:12;:21;;;;;:28;92239:32;;92219:1478;;;92324:21;;;92293:28;92324:21;;;:12;:21;;;;;:24;;92346:1;;92324:24;;;;;;:::i;:::-;;;;;;;;;;;92293:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92363:23;92389:9;:25;;;92363:51;;92504:15;92474:9;:26;;;:45;92470:947;;92707:26;;;;92676:28;;;;;;;:19;:28;;;;;;:57;92672:730;;;92815:28;;;92757:26;92815:28;;;:19;:28;;;;;;92786:26;;;;:57;;92815:28;92786:57;:::i;:::-;92757:86;;92866:25;92912:9;:26;;;92894:15;:44;;;;:::i;:::-;92866:72;-1:-1:-1;93028:17:0;93090:40;92866:72;51201:4;93090:40;:::i;:::-;93049:36;93067:18;93049:15;:36;:::i;:::-;93048:83;;;;:::i;:::-;93028:103;-1:-1:-1;93185:38:0;93206:17;93185:18;:38;:::i;:::-;93172:52;;:9;:52;:::i;:::-;93154:70;;92734:510;;;92672:730;;;-1:-1:-1;51201:4:0;92672:730;93453:19;;;;93433:17;51201:4;93535:43;93553:25;93535:15;:43;:::i;:::-;93522:57;;:9;:57;:::i;:::-;93521:82;;;;:::i;:::-;93487:116;-1:-1:-1;93640:45:0;93487:116;93640:19;:45;:::i;:::-;93618:67;;92278:1419;;;;92273:3;;;;;:::i;:::-;;;;92219:1478;;;;91345:2359;91115:2589;;;;;:::o;76240:161::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;76361:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;76325:68;;::::1;76361:32;::::0;;::::1;76360:33;76325:68;::::0;;76240:161::o;61871:224::-;61937:7;62071:15;;62040:28;;:46;;;;:::i;:::-;61965:5;;:24;;;;;:5;4384:55:1;;;61965:24:0;;;4366:74:1;51201:4:0;;;;61965:5;;;:15;;4339:18:1;;61965:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;75885:97::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;75962:12:::1;::::0;;75946:28;;::::1;75962:12;::::0;;;::::1;;;75961:13;75946:28:::0;;::::1;;::::0;;75885:97::o;65033:278::-;65117:33;;;;;;;:15;:33;;;;;;;;65109:70;;;;;;;15967:2:1;65109:70:0;;;15949:21:1;16006:2;15986:18;;;15979:30;16045:26;16025:18;;;16018:54;16089:18;;65109:70:0;15765:348:1;65109:70:0;65273:10;65248:36;;;;:24;:36;;;;;;;;;:54;;;;;;;;;;;;;;;65247:55;65190:112;;;;;;;65033:278::o;96068:1479::-;96149:10;96161:4;55174:42;55198:7;55207:8;55174:23;:42::i;:::-;96226:28:::1;96256:21:::0;96281:29:::1;96291:10;96303:6;96281:9;:29::i;:::-;96225:85;;;;96397:53;96413:10;96425:9;96436:13;96397:15;:53::i;:::-;-1:-1:-1::0;96381:69:0;-1:-1:-1;96534:1:0::1;96522:13:::0;;;96518:26:::1;;96537:7;;;;96518:26;96593:15;96633:8;96611:9;:19;;;:30;;;;:::i;:::-;96593:48:::0;-1:-1:-1;96812:12:0::1;::::0;96772:91:::1;::::0;96812:12;;::::1;;;96827:10;96847:4;96854:8:::0;96772:31:::1;:91::i;:::-;96947:186;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;96994:25:::0;;::::1;::::0;96947:186;;::::1;::::0;;;;;;;;97056:26;;::::1;::::0;96947:186;;;;;97097:25;;::::1;::::0;96947:186;;;;96918:10:::1;-1:-1:-1::0;96905:24:0;;;:12:::1;:24:::0;;;;;;;:39;;96930:13;;96905:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97204:8;97177:23;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;97241:10:0::1;97223:29;::::0;;;:17:::1;:29;::::0;;;;:41;;97256:8;;97223:29;:41:::1;::::0;97256:8;;97223:41:::1;:::i;:::-;::::0;;;-1:-1:-1;97290:17:0::1;::::0;-1:-1:-1;97310:23:0::1;97322:10;97310:11;:23::i;:::-;97290:43:::0;-1:-1:-1;97352:23:0::1;::::0;::::1;::::0;97348:69:::1;;97377:28;::::0;::::1;;::::0;;;:17:::1;:28:::0;;;;;:40;;97409:8;;97377:28;:40:::1;::::0;97409:8;;97377:40:::1;:::i;:::-;::::0;;;-1:-1:-1;;97348:69:0::1;97275:154;97497:42;97521:10;97533:5;97497:23;:42::i;:::-;96174:1373;;;96068:1479:::0;;;;:::o;69460:172::-;69539:16;45064:1;45670:7;;:19;45662:63;;;;;;;12300:2:1;45662:63:0;;;12282:21:1;12339:2;12319:18;;;12312:30;12378:33;12358:18;;;12351:61;12429:18;;45662:63:0;12098:355:1;45662:63:0;45064:1;45803:18;;69575:49:::1;69586:10;69598:19:::0;69619:4:::1;69575:10;:49::i;:::-;45020:1:::0;45982:7;:22;69568:56;69460:172;-1:-1:-1;;69460:172:0:o;62685:444::-;62764:25;;;62741:7;62764:25;;;:19;:25;;;;;;;;62760:362;;;-1:-1:-1;62967:4:0;62685:444::o;62760:362::-;-1:-1:-1;63079:31:0;;;;;;;;:25;:31;;;;;;;;62685:444::o;75376:311::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;75539:13:::1;:30:::0;;75629:50;::::1;;::::0;::::1;::::0;75580:38;::::1;;::::0;::::1;::::0;75539:30;::::1;;::::0;::::1;75580:38:::0;;;;;;;;;;;;;;;::::1;75629:50:::0;;;::::1;;::::0;;75376:311::o;61415:166::-;61523:26;;;61477:7;61523:26;;;:17;:26;;;;;;61505:15;;51201:4;;61505:44;;;:::i;78586:483::-;54875:5;;78752:20;;54875:5;;54861:10;:19;;:74;;;54884:51;54902:10;54914:20;54884:17;:51::i;:::-;54853:107;;;;;;;15263:2:1;54853:107:0;;;15245:21:1;15302:2;15282:18;;;15275:30;15341:22;15321:18;;;15314:50;15381:18;;54853:107:0;15061:344:1;54853:107:0;78803:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;78785:17:::1;:61:::0;;78849:9;;78803:42;78785:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;78932:25;78869:16;78886:20;:42;78907:20;78886:42;;;;;;;;;;;;;;;;78869:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;78987:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;78968:18:::1;:62:::0;;79033:28;;78987:42;78968:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;78586:483:::0;;;;;:::o;66179:419::-;66259:34;;;;;;;:19;:34;;;;;;;;66251:60;;;;;;;16665:2:1;66251:60:0;;;16647:21:1;16704:2;16684:18;;;16677:30;16743:15;16723:18;;;16716:43;16776:18;;66251:60:0;16463:337:1;66251:60:0;66330:36;;;;;;;:21;:36;;;;;;;;66367:10;66330:48;;;;;;;;;;66322:90;;;;;;;17007:2:1;66322:90:0;;;16989:21:1;17046:2;17026:18;;;17019:30;17085:31;17065:18;;;17058:59;17134:18;;66322:90:0;16805:353:1;66322:90:0;66449:10;66423:37;;;;:25;:37;;;;;;;;:53;;;;:37;:53;;;;;;;;66561:17;:29;;;;;;66525:32;;;;;;;;:65;;66561:29;;66525:32;;:65;;66561:29;;66525:65;:::i;:::-;;;;-1:-1:-1;;;66179:419:0:o;79144:207::-;54875:5;;79252:20;;54875:5;;54861:10;:19;;:74;;;54884:51;54902:10;54914:20;54884:17;:51::i;:::-;54853:107;;;;;;;15263:2:1;54853:107:0;;;15245:21:1;15302:2;15282:18;;;15275:30;15341:22;15321:18;;;15314:50;15381:18;;54853:107:0;15061:344:1;54853:107:0;-1:-1:-1;79285:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;79144:207::o;75780:97::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;75855:14:::1;::::0;;75837:32;;::::1;75855:14;::::0;;::::1;75854:15;75837:32;::::0;;75780:97::o;100137:259::-;100237:7;45064:1;45670:7;;:19;45662:63;;;;;;;12300:2:1;45662:63:0;;;12282:21:1;12339:2;12319:18;;;12312:30;12378:33;12358:18;;;12351:61;12429:18;;45662:63:0;12098:355:1;45662:63:0;45064:1;45803:18;;100265:17:::1;::::0;;;::::1;;;:26;100257:57;;;::::0;::::1;::::0;;17365:2:1;100257:57:0::1;::::0;::::1;17347:21:1::0;17404:2;17384:18;;;17377:30;17443:20;17423:18;;;17416:48;17481:18;;100257:57:0::1;17163:342:1::0;100257:57:0::1;100332:56;100348:10;100360:19;100381:6;100332:15;:56::i;65479:610::-:0;65578:10;65558:31;;;;:19;:31;;;;;;;;65550:57;;;;;;;16665:2:1;65550:57:0;;;16647:21:1;16704:2;16684:18;;;16677:30;16743:15;16723:18;;;16716:43;16776:18;;65550:57:0;16463:337:1;65550:57:0;65693:10;65671:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;65670:50;65618:102;;;;;;;65823:25;:41;;;;;;;;:55;65819:263;;65894:41;;;65946:1;65894:41;;;:25;:41;;;;;;;;:54;;;;;;66037:17;:33;;;;;;66022:10;66004:29;;;;;;;:66;;66037:33;;66004:29;;:66;;66037:33;;66004:66;:::i;65819:263::-;65479:610;:::o;104479:298::-;55030:12;;;;;;;;:20;;:12;:20;55022:49;;;;;;;13105:2:1;55022:49:0;;;13087:21:1;13144:2;13124:18;;;13117:30;13183:18;13163;;;13156:46;13219:18;;55022:49:0;12903:340:1;55022:49:0;104593:40:::1;::::0;::::1;;::::0;;;:24:::1;:40;::::0;;;;;;;104634:10:::1;104593:52:::0;;;;;;;;::::1;;:83:::0;::::1;;;-1:-1:-1::0;104665:10:0::1;104649:27;::::0;;;:15:::1;:27;::::0;;;;;::::1;;104593:83;104585:122;;;::::0;::::1;::::0;;13450:2:1;104585:122:0::1;::::0;::::1;13432:21:1::0;13489:2;13469:18;;;13462:30;13528:28;13508:18;;;13501:56;13574:18;;104585:122:0::1;13248:350:1::0;104585:122:0::1;104718:51;104734:14;104750:10;104762:6;104718:15;:51::i;57428:452::-:0;57489:16;57518:32;57553:16;57570:9;57553:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;57595:38:0;;57591:282;;57776:4;57734:27;57762:9;57734:38;;;;;;;;:::i;:::-;;;;;;;;;57683:24;57662:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;57661:119;;;;:::i;:::-;57650:130;;57591:282;;;57833:17;57851:9;57833:28;;;;;;;;:::i;:::-;;;;;;;;;57822:39;;57507:373;57428:452;;;:::o;74055:761::-;74172:9;74167:642;74191:16;:23;74187:27;;74167:642;;;74236:32;74271:16;74288:1;74271:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;74309:38:0;;74305:493;;74372:12;:61;;;;74407:22;74430:1;74407:25;;;;;;;;:::i;:::-;;;;;;;;;74389:15;:43;74372:61;74368:415;;;74547:106;;;;;74630:4;74547:106;;;17684:74:1;74637:15:0;17774:18:1;;;17767:34;74547:74:0;;;;;;17657:18:1;;74547:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74514:27;74542:1;74514:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;74725:24;74704:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74676:22;74699:1;74676:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;74368:415;-1:-1:-1;74216:3:0;;;;:::i;:::-;;;;74167:642;;;;74055:761;:::o;77551:958::-;54672:5;;;;54658:10;:19;;:79;;-1:-1:-1;54695:42:0;54681:10;:56;54658:79;54650:113;;;;;;;13805:2:1;54650:113:0;;;13787:21:1;13844:2;13824:18;;;13817:30;13883:23;13863:18;;;13856:51;13924:18;;54650:113:0;13603:345:1;54650:113:0;77960:13;;51201:4:::1;-1:-1:-1::0;77960:37:0::1;77952:69;;;::::0;::::1;::::0;;18014:2:1;77952:69:0::1;::::0;::::1;17996:21:1::0;18053:2;18033:18;;;18026:30;18092:21;18072:18;;;18065:49;18131:18;;77952:69:0::1;17812:343:1::0;77952:69:0::1;78145:13:::0;;::::1;::::0;78162:1:::1;-1:-1:-1::0;78145:18:0;::::1;::::0;78144:44:::1;;-1:-1:-1::0;78169:13:0;;::::1;::::0;78186:1:::1;-1:-1:-1::0;78169:18:0::1;78144:44;78136:69;;;::::0;::::1;::::0;;18703:2:1;78136:69:0::1;::::0;::::1;18685:21:1::0;18742:2;18722:18;;;18715:30;18781:14;18761:18;;;18754:42;18813:18;;78136:69:0::1;18501:336:1::0;78136:69:0::1;78240:13:::0;;78218:19:::1;:35:::0;78240:13:::1;78287::::0;::::1;::::0;78264:20:::1;:36:::0;78342:13;;::::1;::::0;78311:28:::1;:44:::0;78393:13;;::::1;::::0;78366:24:::1;:40:::0;78448:13;;::::1;::::0;78417:28:::1;:44:::0;78488:13;::::1;::::0;78472::::1;:29:::0;77551:958::o;74824:363::-;74907:25;74926:5;74907:18;:25::i;:::-;90948:4;74984:15;:34;75054:12;;75035:15;:31;75031:149;;75083:14;:12;:14::i;:::-;74824:363::o;75031:149::-;75139:29;:27;:29::i;522:106::-;580:7;611:1;607;:5;:13;;619:1;607:13;;;615:1;607:13;600:20;522:106;-1:-1:-1;;;522:106:0:o;98062:1901::-;98305:7;98274:14;98290:4;55174:42;55198:7;55207:8;55174:23;:42::i;:::-;98333:13:::1;::::0;;;::::1;;;:22;::::0;:61:::1;;-1:-1:-1::0;98375:10:0::1;98359:27;::::0;;;:15:::1;:27;::::0;;;;;::::1;;:35;;:27:::0;:35:::1;98333:61;98325:104;;;::::0;::::1;::::0;;19044:2:1;98325:104:0::1;::::0;::::1;19026:21:1::0;19083:2;19063:18;;;19056:30;19122:32;19102:18;;;19095:60;19172:18;;98325:104:0::1;18842:354:1::0;98325:104:0::1;98456:13;;98448:4;:21;;98440:60;;;::::0;::::1;::::0;;19403:2:1;98440:60:0::1;::::0;::::1;19385:21:1::0;19442:2;19422:18;;;19415:30;19481:28;19461:18;;;19454:56;19527:18;;98440:60:0::1;19201:350:1::0;98440:60:0::1;98527:28;;98519:4;:36;;98511:75;;;::::0;::::1;::::0;;19758:2:1;98511:75:0::1;::::0;::::1;19740:21:1::0;19797:2;19777:18;;;19770:30;19836:29;19816:18;;;19809:57;19883:18;;98511:75:0::1;19556:351:1::0;98511:75:0::1;98709:12;::::0;98669:96:::1;::::0;98709:12;;::::1;;;98724:14:::0;98748:4:::1;98755:9:::0;98669:31:::1;:96::i;:::-;98825:23;98851:20;98866:4;98851:14;:20::i;:::-;98970:33;::::0;::::1;98882:14;98970:33:::0;;;:17:::1;:33;::::0;;;;;;;;98909:95;;20158:66:1;20145:2;20141:15;;;20137:88;98909:95:0;;::::1;20125:101:1::0;;;;20242:12;;;20235:28;;;20279:12;;;20272:28;;;20316:12;;;20309:28;98825:46:0;;-1:-1:-1;98882:14:0;20353:13:1;;98909:95:0::1;::::0;;;;;::::1;::::0;;;;;;98899:106;;98909:95:::1;98899:106:::0;;::::1;::::0;99062:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;99096:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;98899:106;;-1:-1:-1;99062:28:0;99096:164;;;99197:22:::1;99215:4:::0;99143:15;99197:22:::1;:::i;:::-;99096:164:::0;;::::1;::::0;;::::1;::::0;;;99062:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;99062: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;99392:12:::1;:10;:12::i;:::-;99366:23;::::0;;;:15:::1;:23;::::0;;;;:38;;;;99448:23:::1;:36:::0;;99475:9;;99366:23;99448:36:::1;::::0;99475:9;;99448:36:::1;:::i;:::-;::::0;;;-1:-1:-1;;99495:33:0::1;::::0;::::1;;::::0;;;:17:::1;:33;::::0;;;;:46;;99532:9;;99495:33;:46:::1;::::0;99532:9;;99495:46:::1;:::i;:::-;::::0;;;-1:-1:-1;99567:17:0::1;::::0;-1:-1:-1;99587:27:0::1;99599:14:::0;99587:11:::1;:27::i;:::-;99567:47:::0;-1:-1:-1;99633:23:0::1;::::0;::::1;::::0;99629:70:::1;;99658:28;::::0;::::1;;::::0;;;:17:::1;:28:::0;;;;;:41;;99690:9;;99658:28;:41:::1;::::0;99690:9;;99658:41:::1;:::i;:::-;::::0;;;-1:-1:-1;;99629:70:0::1;99552:159;99797:46;99821:14;99837:5;99797:23;:46::i;:::-;99861:68;::::0;;20608:25:1;;;20664:2;20649:18;;20642:34;;;20692:18;;;20685:34;;;99861:68:0::1;20755:55:1::0;;;20750:2;20735:18;;20728:83;99861:68:0;::::1;::::0;::::1;::::0;20595:3:1;20580:19;99861:68:0::1;;;;;;;99949:6:::0;98062:1901;-1:-1:-1;;;;;;;;;98062:1901:0:o;57287:133::-;57346:7;57373:39;57382:15;57399:12;;57373:8;:39::i;69942:1006::-;70087:31;70062:8;70072:4;55174:42;55198:7;55207:8;55174:23;:42::i;:::-;70193:23:::1;::::0;;;::::1;;;:32;70185:70;;;::::0;::::1;::::0;;14155:2:1;70185:70:0::1;::::0;::::1;14137:21:1::0;14194:2;14174:18;;;14167:30;14233:27;14213:18;;;14206:55;14278:18;;70185:70:0::1;13953:349:1::0;70185:70:0::1;70367:12;:19:::0;70353:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;70353:34:0::1;;70336:51;;70405:9;70400:282;70424:12;:19:::0;70420:23;::::1;70400:282;;;70485:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;70465:17;;:14;;70503:1;;70465:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;70520:17:::1;::::0;::::1;70543:1;70520:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;70563:17;;:14;;70538:1;;70563:17;::::1;;;;;:::i;:::-;;;;;;;:21;70559:111;;;70586:84;70614:12;70627:1;70614:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;70631:19;70652:14;70667:1;70652:17;;;;;;;;:::i;:::-;;;;;;;70586:27;:84::i;:::-;70445:3:::0;::::1;::::0;::::1;:::i;:::-;;;;70400:282;;;;-1:-1:-1::0;;70893:29:0::1;::::0;;::::1;;::::0;;;:19:::1;:29;::::0;;;;70925:15:::1;70893:47:::0;;-1:-1:-1;69942:1006:0;;;-1:-1:-1;69942:1006:0:o;38700:361::-;38895:45;;;38884:10;17702:55:1;;;38895:45:0;;;17684:74:1;17774:18;;;;17767:34;;;38895:45:0;;;;;;;;;;17657:18:1;;;;38895:45:0;;;;;;;;;;;;;38884:57;;-1:-1:-1;;;;38884:10:0;;;;:57;;38895:45;38884:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38848:93;;;;38960:7;:57;;;;-1:-1:-1;38972:11:0;;:16;;:44;;;39003:4;38992:24;;;;;;;;;;;;:::i;:::-;38952:101;;;;;;;21816:2:1;38952:101:0;;;21798:21:1;21855:2;21835:18;;;21828:30;21894:33;21874:18;;;21867:61;21945:18;;38952:101:0;21614:355:1;66764:1525:0;66954:8;66950:46;;;66978:6;:4;:6::i;:::-;67020:21;;;;67016:1266;;67234:27;67280:28;67327:27;67372:30;67394:7;67372:21;:30::i;:::-;67212:190;;;;;;67464:20;67476:7;67464:11;:20::i;:::-;67560:31;;;;;;;:22;:31;;;;;:54;;;67701:42;;;67697:572;;67764:19;67786:41;67808:19;67786;:41;:::i;:::-;67764:63;;67896:11;67871:22;;:36;;;;:::i;:::-;67846:22;:61;67955:33;67977:11;67955:19;:33;:::i;:::-;67926:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;67697:572:0;;;68029:19;68051:41;68073:19;68051;:41;:::i;:::-;68029:63;;68161:11;68136:22;;:36;;;;:::i;:::-;68111:22;:61;68220:33;68242:11;68220:19;:33;:::i;:::-;68191:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;67043:1239:0;;;66764:1525;;:::o;95414:508::-;95496:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95496:31:0;95529:15;;95557:280;95581:28;;;;;;;:12;:28;;;;;:35;95577:39;;95557:280;;;95652:28;;;;;;;:12;:28;;;;;:31;;95681:1;;95652:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;95642:6;:48;95638:188;;95725:28;;;;;;;:12;:28;;;;;:31;;95754:1;;95725:31;;;;;;:::i;:::-;;;;;;;;;;;95710:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95785:1;95775:11;;95805:5;;95638:188;95618:3;;;;:::i;:::-;;;;95557:280;;;-1:-1:-1;95855:19:0;;:29;;95847:57;;;;;;;22176:2:1;95847:57:0;;;22158:21:1;22215:2;22195:18;;;22188:30;22254:17;22234:18;;;22227:45;22289:18;;95847:57:0;21974:339:1;95847:57:0;95414:508;;;;;:::o;102566:1172::-;102722:18;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102722:18:0;102988:16;;102742:7;102972:33;;;:15;:33;;;;;;102742:7;;102956:12;:10;:12::i;:::-;102934:9;:19;;;:34;;;;:::i;:::-;102933:72;;;;:::i;:::-;102915:90;;103016:16;103045:9;:19;;;103035:7;:29;;;;:::i;:::-;103114:28;;;;;;;:12;:28;;;;;:43;;103016:48;;-1:-1:-1;103170:7:0;;103143:13;;103114:43;;;;;;:::i;:::-;;;;;;;;;;;:53;;:63;;;;103257:8;103230:23;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;;103276:33:0;;;;;;;:17;:33;;;;;:45;;103313:8;;103276:33;:45;;103313:8;;103276:45;:::i;:::-;;;;-1:-1:-1;103347:17:0;;-1:-1:-1;103367:27:0;103379:14;103367:11;:27::i;:::-;103347:47;-1:-1:-1;103413:23:0;;;;103409:69;;103438:28;;;;;;;:17;:28;;;;;:40;;103470:8;;103438:28;:40;;103470:8;;103438:40;:::i;:::-;;;;-1:-1:-1;;103409:69:0;103332:158;103634:12;:10;:12::i;:::-;103614:16;;103598:33;;;;:15;:33;;;;;;;;:48;;;;103671:28;;;;;:12;:28;;;:43;;103700:13;;103671:43;;;;;;:::i;:::-;;;;;;;;;;;103716:13;103663:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102566:1172;;;;;;:::o;39069:402::-;39294:51;;;39283:10;22599:15:1;;;39294:51:0;;;22581:34:1;22651:15;;;22631:18;;;22624:43;22683:18;;;;22676:34;;;39294:51:0;;;;;;;;;;22493:18:1;;;;39294:51:0;;;;;;;;;;;;;39283:63;;-1:-1:-1;;;;39283:10:0;;;;:63;;39294:51;39283:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39247:99;;;;39365:7;:57;;;;-1:-1:-1;39377:11:0;;:16;;:44;;;39408:4;39397:24;;;;;;;;;;;;:::i;:::-;39357:106;;;;;;;22923:2:1;39357:106:0;;;22905:21:1;22962:2;22942:18;;;22935:30;23001:34;22981:18;;;22974:62;23072:6;23052:18;;;23045:34;23096:19;;39357:106:0;22721:400:1;39357:106:0;39157:314;;39069:402;;;;:::o;100602:1840::-;100748:7;100831:53;100842:14;100858:19;100879:4;100831:10;:53::i;:::-;;100938:28;100968:21;100993:33;101003:14;101019:6;100993:9;:33::i;:::-;100937:89;;;;101113:57;101129:14;101145:9;101156:13;101113:15;:57::i;:::-;-1:-1:-1;101239:26:0;;;;101097:73;;-1:-1:-1;101220:15:0;:45;;;:71;;-1:-1:-1;101269:14:0;;;;:22;;:14;:22;101220:71;:110;;;-1:-1:-1;101311:10:0;101295:27;;;;:15;:27;;;;;;;;:35;;:27;:35;101220:110;101212:145;;;;;;;23328:2:1;101212:145:0;;;23310:21:1;23367:2;23347:18;;;23340:30;23406:24;23386:18;;;23379:52;23448:18;;101212:145:0;23126:346:1;101212:145:0;101388:19;;;;101424:13;;101420:986;;101516:9;101489:23;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;101540:33:0;;;;;;;:17;:33;;;;;:46;;101577:9;;101540:33;:46;;101577:9;;101540:46;:::i;:::-;;;;-1:-1:-1;101620:17:0;;-1:-1:-1;101640:27:0;101652:14;101640:11;:27::i;:::-;101620:47;-1:-1:-1;101690:23:0;;;;101686:70;;101715:28;;;;;;;:17;:28;;;;;:41;;101747:9;;101715:28;:41;;101747:9;;101715:41;:::i;:::-;;;;-1:-1:-1;;101686:70:0;-1:-1:-1;101843:28:0;;;;;;;:12;:28;;;;;:43;;101872:13;;101843:43;;;;;;:::i;:::-;;;;;;;;;;;;;;101836:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102015:12;;;:53;;;;;:12;17702:55:1;;;102015:53:0;;;17684:74:1;;;;17774:18;;;17767:34;;;102015:12:0;;;;;;;:21;;17657:18:1;;102015:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;102155:46;102179:14;102195:5;102155:23;:46::i;:::-;102308:70;;;23679:25:1;;;23735:2;23720:18;;23713:34;;;102308:70:0;23783:55:1;;;23763:18;;;23756:83;102308:70:0;;;;;;;;;;;23667:2:1;102308:70:0;;;101420:986;102425:9;100602:1840;-1:-1:-1;;;;;;100602:1840:0:o;71035:2569::-;71156:9;71151:327;71175:18;:25;71171:29;;71151:327;;;71222:34;71259:18;71278:1;71259:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;71299:40:0;;71295:172;;71360:91;;;;;71445:4;71360:91;;;4366:74:1;71360:76:0;;;;;;4339:18:1;;71360:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;71295:172;-1:-1:-1;71202:3:0;;;;:::i;:::-;;;;71151:327;;;;71838:27;52713:6;71894:12;;71876:15;:30;;;;:::i;:::-;71868:57;;;;:::i;:::-;71838:87;;72064:9;72059:283;72083:12;:19;72079:23;;72059:283;;;72204:12;72217:1;72204:15;;;;;;;;:::i;:::-;;;;;;;;;;;72198:47;;;;;72239:4;72198:47;;;4366:74:1;72204:15:0;;;;;72198:32;;4339:18:1;;72198:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72169:23;:19;72191:1;72169:23;:::i;:::-;52713:6;72133:14;72145:1;72133:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;72132:113;;72311:12;72324:1;72311:15;;;;;;;;:::i;:::-;;;;;;;;;;;;72254:73;;;24342:34:1;72254:73:0;;;24330:47:1;;;;24407:6;24393:12;;;24386:28;24452:2;24448:15;;;24430:12;;;24423:110;24549:12;;72254:73:0;;;;;;;;;;;;72124:206;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;72104:3:0;;;;:::i;:::-;;;;72059:283;;;-1:-1:-1;52713:6:0;72554:23;:19;72576:1;72554:23;:::i;:::-;72553:43;;;;:::i;:::-;72537:12;;:60;;;;:::i;:::-;72522:12;:75;72650:29;:27;:29::i;:::-;90948:4;72731:15;:34;72963:17;:20;;72981:1;;72963:20;;;;;;:::i;:::-;;;;;;;;;72987:1;72963:25;72959:634;;73115:16;;;73129:1;73115:16;;;;;;;;;73085:27;;73115:16;;;;;;;;;;;-1:-1:-1;73115:16:0;73085:46;;73162:42;73146:10;73157:1;73146:13;;;;;;;;:::i;:::-;:58;;;;:13;;;;;;;;;;;:58;73251:262;;;;;73228:20;;73284:42;;73251:89;;:262;;73359:10;;73388:78;;73493:4;;73251:262;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73228:285;-1:-1:-1;73551:30:0;52713:6;73228:285;73551:30;:::i;:::-;73528:17;73546:1;73528:20;;;;;;;;:::i;:::-;;;;;;;;;;:53;-1:-1:-1;;71068:2536:0;71035:2569::o;73612:435::-;73699:34;73736:17;:15;:17::i;:::-;73699:54;;73816:9;73811:133;73835:21;:28;73831:32;;73811:133;;;73912:17;73930:1;73912:20;;;;;;;;:::i;:::-;;;;;;;73885:21;73907:1;73885:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;73865:3;;;;:::i;:::-;;;;73811:133;;;;74013:26;:24;:26::i;:::-;73996:14;:43;-1:-1:-1;73612:435:0:o;68297:585::-;68359:21;;;;68355:520;;68436:27;68466:15;68473:7;68466:6;:15::i;:::-;68436:45;;68544:9;68539:118;68563:10;:17;68559:1;:21;68539:118;;;68628:10;68639:1;68628:13;;;;;;;;:::i;:::-;;;;;;;;;;;;68606:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;68623:1;68582:3;68623:1;68582:3;:::i;:::-;;;;68539:118;;;;68724:9;68719:145;68743:10;:17;68739:1;:21;68719:145;;;68824:21;68846:1;68824:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;68786:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;68819:1;68762:3;68819:1;68762:3;:::i;:::-;;;;68719:145;;14:154:1;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:247;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;340:9;327:23;359:31;384:5;359:31;:::i;425:632::-;596:2;648:21;;;718:13;;621:18;;;740:22;;;567:4;;596:2;819:15;;;;793:2;778:18;;;567:4;862:169;876:6;873:1;870:13;862:169;;;937:13;;925:26;;1006:15;;;;971:12;;;;898:1;891:9;862:169;;;-1:-1:-1;1048:3:1;;425:632;-1:-1:-1;;;;;;425:632:1:o;1062:180::-;1121:6;1174:2;1162:9;1153:7;1149:23;1145:32;1142:52;;;1190:1;1187;1180:12;1142:52;-1:-1:-1;1213:23:1;;1062:180;-1:-1:-1;1062:180:1:o;1429:484::-;1482:3;1520:5;1514:12;1547:6;1542:3;1535:19;1573:4;1602:2;1597:3;1593:12;1586:19;;1639:2;1632:5;1628:14;1660:1;1670:218;1684:6;1681:1;1678:13;1670:218;;;1749:13;;1764:42;1745:62;1733:75;;1828:12;;;;1863:15;;;;1706:1;1699:9;1670:218;;;-1:-1:-1;1904:3:1;;1429:484;-1:-1:-1;;;;;1429:484:1:o;1918:261::-;2097:2;2086:9;2079:21;2060:4;2117:56;2169:2;2158:9;2154:18;2146:6;2117:56;:::i;2184:248::-;2252:6;2260;2313:2;2301:9;2292:7;2288:23;2284:32;2281:52;;;2329:1;2326;2319:12;2281:52;-1:-1:-1;;2352:23:1;;;2422:2;2407:18;;;2394:32;;-1:-1:-1;2184:248:1:o;2619:1011::-;2848:2;2900:21;;;2970:13;;2873:18;;;2992:22;;;2819:4;;2848:2;3033;;3051:18;;;;3092:15;;;2819:4;3135:469;3149:6;3146:1;3143:13;3135:469;;;3208:13;;3246:9;;3234:22;;3296:11;;;3290:18;3276:12;;;3269:40;3349:11;;;3343:18;3329:12;;;3322:40;3385:4;3429:11;;;3423:18;3409:12;;;3402:40;3465:4;3509:11;;;3503:18;3489:12;;;3482:40;3551:4;3542:14;;;;3579:15;;;;3171:1;3164:9;3135:469;;;-1:-1:-1;3621:3:1;;2619:1011;-1:-1:-1;;;;;;;2619:1011:1:o;3635:388::-;3703:6;3711;3764:2;3752:9;3743:7;3739:23;3735:32;3732:52;;;3780:1;3777;3770:12;3732:52;3819:9;3806:23;3838:31;3863:5;3838:31;:::i;:::-;3888:5;-1:-1:-1;3945:2:1;3930:18;;3917:32;3958:33;3917:32;3958:33;:::i;:::-;4010:7;4000:17;;;3635:388;;;;;:::o;4451:452::-;4537:6;4545;4553;4561;4614:3;4602:9;4593:7;4589:23;4585:33;4582:53;;;4631:1;4628;4621:12;4582:53;4670:9;4657:23;4689:31;4714:5;4689:31;:::i;:::-;4739:5;4791:2;4776:18;;4763:32;;-1:-1:-1;4842:2:1;4827:18;;4814:32;;4893:2;4878:18;4865:32;;-1:-1:-1;4451:452:1;-1:-1:-1;;;4451:452:1:o;5155:118::-;5241:5;5234:13;5227:21;5220:5;5217:32;5207:60;;5263:1;5260;5253:12;5278:382;5343:6;5351;5404:2;5392:9;5383:7;5379:23;5375:32;5372:52;;;5420:1;5417;5410:12;5372:52;5459:9;5446:23;5478:31;5503:5;5478:31;:::i;:::-;5528:5;-1:-1:-1;5585:2:1;5570:18;;5557:32;5598:30;5557:32;5598:30;:::i;5665:315::-;5733:6;5741;5794:2;5782:9;5773:7;5769:23;5765:32;5762:52;;;5810:1;5807;5800:12;5762:52;5849:9;5836:23;5868:31;5893:5;5868:31;:::i;:::-;5918:5;5970:2;5955:18;;;;5942:32;;-1:-1:-1;;;5665:315:1:o;7215:511::-;7283:6;7291;7299;7352:2;7340:9;7331:7;7327:23;7323:32;7320:52;;;7368:1;7365;7358:12;7320:52;7407:9;7394:23;7426:28;7448:5;7426:28;:::i;:::-;7473:5;-1:-1:-1;7530:2:1;7515:18;;7502:32;7543:30;7502:32;7543:30;:::i;:::-;7592:7;-1:-1:-1;7651:2:1;7636:18;;7623:32;7664:30;7623:32;7664:30;:::i;:::-;7713:7;7703:17;;;7215:511;;;;;:::o;7731:598::-;7817:6;7825;7833;7841;7894:3;7882:9;7873:7;7869:23;7865:33;7862:53;;;7911:1;7908;7901:12;7862:53;7950:9;7937:23;7969:31;7994:5;7969:31;:::i;:::-;8019:5;-1:-1:-1;8071:2:1;8056:18;;8043:32;;-1:-1:-1;8127:2:1;8112:18;;8099:32;8140:33;8099:32;8140:33;:::i;:::-;8192:7;-1:-1:-1;8251:2:1;8236:18;;8223:32;8264:33;8223:32;8264:33;:::i;:::-;7731:598;;;;-1:-1:-1;7731:598:1;;-1:-1:-1;;7731:598:1:o;8334:315::-;8402:6;8410;8463:2;8451:9;8442:7;8438:23;8434:32;8431:52;;;8479:1;8476;8469:12;8431:52;8515:9;8502:23;8492:33;;8575:2;8564:9;8560:18;8547:32;8588:31;8613:5;8588:31;:::i;8974:241::-;9030:6;9083:2;9071:9;9062:7;9058:23;9054:32;9051:52;;;9099:1;9096;9089:12;9051:52;9138:9;9125:23;9157:28;9179:5;9157:28;:::i;9220:184::-;9272:77;9269:1;9262:88;9369:4;9366:1;9359:15;9393:4;9390:1;9383:15;9409:915;9491:6;9544:3;9532:9;9523:7;9519:23;9515:33;9512:53;;;9561:1;9558;9551:12;9512:53;9610:7;9603:4;9592:9;9588:20;9584:34;9574:62;;9632:1;9629;9622:12;9574:62;9665:2;9659:9;9707:3;9699:6;9695:16;9777:6;9765:10;9762:22;9741:18;9729:10;9726:34;9723:62;9720:242;;;9818:77;9815:1;9808:88;9919:4;9916:1;9909:15;9947:4;9944:1;9937:15;9720:242;9978:2;9971:22;10013:6;10057:3;10042:19;;10073;;;10070:39;;;10105:1;10102;10095:12;10070:39;10129:9;10147:146;10163:6;10158:3;10155:15;10147:146;;;10231:17;;10219:30;;10278:4;10269:14;;;;10180;10147:146;;;-1:-1:-1;10312:6:1;;9409:915;-1:-1:-1;;;;;9409:915:1:o;10329:184::-;10381:77;10378:1;10371:88;10478:4;10475:1;10468:15;10502:4;10499:1;10492:15;10518:184;10570:77;10567:1;10560:88;10667:4;10664:1;10657:15;10691:4;10688:1;10681:15;10707:125;10747:4;10775:1;10772;10769:8;10766:34;;;10780:18;;:::i;:::-;-1:-1:-1;10817:9:1;;10707:125::o;10837:228::-;10877:7;11003:1;10935:66;10931:74;10928:1;10925:81;10920:1;10913:9;10906:17;10902:105;10899:131;;;11010:18;;:::i;:::-;-1:-1:-1;11050:9:1;;10837:228::o;11070:274::-;11110:1;11136;11126:189;;11171:77;11168:1;11161:88;11272:4;11269:1;11262:15;11300:4;11297:1;11290:15;11126:189;-1:-1:-1;11329:9:1;;11070:274::o;11349:128::-;11389:3;11420:1;11416:6;11413:1;11410:13;11407:39;;;11426:18;;:::i;:::-;-1:-1:-1;11462:9:1;;11349:128::o;11482:195::-;11521:3;11552:66;11545:5;11542:77;11539:103;;11622:18;;:::i;:::-;-1:-1:-1;11669:1:1;11658:13;;11482:195::o;12458:251::-;12528:6;12581:2;12569:9;12560:7;12556:23;12552:32;12549:52;;;12597:1;12594;12587:12;12549:52;12629:9;12623:16;12648:31;12673:5;12648:31;:::i;12714:184::-;12784:6;12837:2;12825:9;12816:7;12812:23;12808:32;12805:52;;;12853:1;12850;12843:12;12805:52;-1:-1:-1;12876:16:1;;12714:184;-1:-1:-1;12714:184:1:o;20822:258::-;20894:1;20904:113;20918:6;20915:1;20912:13;20904:113;;;20994:11;;;20988:18;20975:11;;;20968:39;20940:2;20933:10;20904:113;;;21035:6;21032:1;21029:13;21026:48;;;-1:-1:-1;;21070:1:1;21052:16;;21045:27;20822:258::o;21085:274::-;21214:3;21252:6;21246:13;21268:53;21314:6;21309:3;21302:4;21294:6;21290:17;21268:53;:::i;:::-;21337:16;;;;;21085:274;-1:-1:-1;;21085:274:1:o;21364:245::-;21431:6;21484:2;21472:9;21463:7;21459:23;21455:32;21452:52;;;21500:1;21497;21490:12;21452:52;21532:9;21526:16;21551:28;21573:5;21551:28;:::i;23850:245::-;23929:6;23937;23990:2;23978:9;23969:7;23965:23;23961:32;23958:52;;;24006:1;24003;23996:12;23958:52;-1:-1:-1;;24029:16:1;;24085:2;24070:18;;;24064:25;24029:16;;24064:25;;-1:-1:-1;23850:245:1:o;24572:442::-;24721:2;24710:9;24703:21;24684:4;24753:6;24747:13;24796:6;24791:2;24780:9;24776:18;24769:34;24812:66;24871:6;24866:2;24855:9;24851:18;24846:2;24838:6;24834:15;24812:66;:::i;:::-;24930:2;24918:15;24935:66;24914:88;24899:104;;;;25005:2;24895:113;;24572:442;-1:-1:-1;;24572:442:1:o;25019:537::-;25339:2;25328:9;25321:21;25302:4;25359:56;25411:2;25400:9;25396:18;25388:6;25359:56;:::i;:::-;25351:64;;25451:6;25446:2;25435:9;25431:18;25424:34;25506:42;25498:6;25494:55;25489:2;25478:9;25474:18;25467:83;25019:537;;;;;;:::o
Swarm Source
ipfs://62234020a79da5894696814a693b51a31d672a6e51f17fa40d3cc3868dc56bea
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.