Source Code
Latest 25 from a total of 1,945 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw Locked | 24490919 | 15 days ago | IN | 0 ETH | 0.00088913 | ||||
| Sync | 24407701 | 27 days ago | IN | 0 ETH | 0.00001554 | ||||
| Withdraw Locked | 23656555 | 132 days ago | IN | 0 ETH | 0.0003986 | ||||
| Withdraw Locked | 23656548 | 132 days ago | IN | 0 ETH | 0.00059163 | ||||
| Withdraw Locked | 22574719 | 283 days ago | IN | 0 ETH | 0.00336369 | ||||
| Withdraw Locked | 22388169 | 309 days ago | IN | 0 ETH | 0.0002857 | ||||
| Get Reward | 22388163 | 309 days ago | IN | 0 ETH | 0.00040606 | ||||
| Withdraw Locked | 22255091 | 328 days ago | IN | 0 ETH | 0.00026657 | ||||
| Withdraw Locked | 22189575 | 337 days ago | IN | 0 ETH | 0.00059615 | ||||
| Withdraw Locked | 22186583 | 337 days ago | IN | 0 ETH | 0.0004436 | ||||
| Withdraw Locked | 22184056 | 338 days ago | IN | 0 ETH | 0.00077322 | ||||
| Withdraw Locked | 22184034 | 338 days ago | IN | 0 ETH | 0.00092787 | ||||
| Get Reward | 22184027 | 338 days ago | IN | 0 ETH | 0.00085681 | ||||
| Withdraw Locked | 22137978 | 344 days ago | IN | 0 ETH | 0.00056088 | ||||
| Withdraw Locked | 21682043 | 408 days ago | IN | 0 ETH | 0.00367944 | ||||
| Withdraw Locked | 21682039 | 408 days ago | IN | 0 ETH | 0.00313523 | ||||
| Withdraw Locked | 21682035 | 408 days ago | IN | 0 ETH | 0.00487427 | ||||
| Withdraw Locked | 21670076 | 409 days ago | IN | 0 ETH | 0.00540184 | ||||
| Withdraw Locked | 21630725 | 415 days ago | IN | 0 ETH | 0.009086 | ||||
| Withdraw Locked | 21603658 | 419 days ago | IN | 0 ETH | 0.00210617 | ||||
| Withdraw Locked | 21573017 | 423 days ago | IN | 0 ETH | 0.00456124 | ||||
| Withdraw Locked | 21555219 | 425 days ago | IN | 0 ETH | 0.00339503 | ||||
| Withdraw Locked | 21522961 | 430 days ago | IN | 0 ETH | 0.00561171 | ||||
| Get Reward | 21522956 | 430 days ago | IN | 0 ETH | 0.00437664 | ||||
| Withdraw Locked | 21522247 | 430 days ago | IN | 0 ETH | 0.00421706 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StakingRewardsMultiGauge_StakeDAO
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-09-14
*/
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
// Sources flattened with hardhat v2.6.2 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/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/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/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/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/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/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/Misc_AMOs/stakedao/IStakeDaoVault.sol
interface IStakeDaoVault {
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function available() external view returns (uint256);
function balance() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function controller() external view returns (address);
function decimals() external view returns (uint8);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
function deposit(uint256 _amount) external;
function depositAll() external;
function earn() external;
function getPricePerFullShare() external view returns (uint256);
function governance() external view returns (address);
function harvest(address reserve, uint256 amount) external;
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function max() external view returns (uint256);
function min() external view returns (uint256);
function name() external view returns (string memory);
function setController(address _controller) external;
function setGovernance(address _governance) external;
function setMin(uint256 _min) external;
function symbol() external view returns (string memory);
function token() external view returns (address);
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function withdraw(uint256 _shares) external;
function withdrawAll() external;
}
// // Part: IController
// interface IController {
// function withdraw(address, uint256) external;
// function balanceOf(address) external view returns (uint256);
// function earn(address, uint256) external;
// function want(address) external view returns (address);
// function rewards() external view returns (address);
// function vaults(address) external view returns (address);
// function strategies(address) external view returns (address);
// }
// // Part: OpenZeppelin/[email protected]/Address
// /**
// * @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) {
// // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// // for accounts without code, i.e. `keccak256('')`
// bytes32 codehash;
// bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// // solhint-disable-next-line no-inline-assembly
// assembly { codehash := extcodehash(account) }
// return (codehash != accountHash && codehash != 0x0);
// }
// /**
// * @dev Converts an `address` into `address payable`. Note that this is
// * simply a type cast: the actual underlying value is not changed.
// *
// * _Available since v2.4.0._
// */
// function toPayable(address account) internal pure returns (address payable) {
// return address(uint160(account));
// }
// /**
// * @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].
// *
// * _Available since v2.4.0._
// */
// function sendValue(address payable recipient, uint256 amount) internal {
// require(address(this).balance >= amount, "Address: insufficient balance");
// // solhint-disable-next-line avoid-call-value
// (bool success, ) = recipient.call.value(amount)("");
// require(success, "Address: unable to send value, recipient may have reverted");
// }
// }
// // Part: OpenZeppelin/[email protected]/Context
// /*
// * @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.
// */
// contract Context {
// // Empty internal constructor, to prevent people from mistakenly deploying
// // an instance of this contract, which should be used via inheritance.
// constructor () internal { }
// // solhint-disable-previous-line no-empty-blocks
// function _msgSender() internal view returns (address payable) {
// return msg.sender;
// }
// function _msgData() internal view returns (bytes memory) {
// this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
// return msg.data;
// }
// }
// // Part: OpenZeppelin/[email protected]/IERC20
// /**
// * @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);
// }
// // Part: OpenZeppelin/[email protected]/SafeMath
// /**
// * @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;
// }
// }
// // Part: OpenZeppelin/[email protected]/ERC20
// /**
// * @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;
// /**
// * @dev See {IERC20-totalSupply}.
// */
// function totalSupply() public view returns (uint256) {
// return _totalSupply;
// }
// /**
// * @dev See {IERC20-balanceOf}.
// */
// function balanceOf(address account) public view 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 returns (bool) {
// _transfer(_msgSender(), recipient, amount);
// return true;
// }
// /**
// * @dev See {IERC20-allowance}.
// */
// function allowance(address owner, address spender) public view returns (uint256) {
// return _allowances[owner][spender];
// }
// /**
// * @dev See {IERC20-approve}.
// *
// * Requirements:
// *
// * - `spender` cannot be the zero address.
// */
// function approve(address spender, uint256 amount) public 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 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 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 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 {
// require(sender != address(0), "ERC20: transfer from the zero address");
// require(recipient != address(0), "ERC20: transfer to the zero address");
// _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 {
// require(account != address(0), "ERC20: mint to the zero address");
// _totalSupply = _totalSupply.add(amount);
// _balances[account] = _balances[account].add(amount);
// emit Transfer(address(0), 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 {
// require(account != address(0), "ERC20: burn from the zero address");
// _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 {
// 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 {
// _burn(account, amount);
// _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
// }
// }
// // Part: OpenZeppelin/[email protected]/ERC20Detailed
// /**
// * @dev Optional functions from the ERC20 standard.
// */
// contract ERC20Detailed is IERC20 {
// string private _name;
// string private _symbol;
// uint8 private _decimals;
// /**
// * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
// * these values are immutable: they can only be set once during
// * construction.
// */
// constructor (string memory name, string memory symbol, uint8 decimals) public {
// _name = name;
// _symbol = symbol;
// _decimals = decimals;
// }
// /**
// * @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.
// *
// * 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;
// }
// }
// // Part: OpenZeppelin/[email protected]/SafeERC20
// /**
// * @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 ERC20;` 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));
// }
// 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.
// // A Solidity high level call has three parts:
// // 1. The target address is checked to verify it contains contract code
// // 2. The call itself is made, and success asserted
// // 3. The return value is decoded, which in turn checks the size of the returned data.
// // solhint-disable-next-line max-line-length
// require(address(token).isContract(), "SafeERC20: call to non-contract");
// // solhint-disable-next-line avoid-low-level-calls
// (bool success, bytes memory returndata) = address(token).call(data);
// require(success, "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: Vault.sol
// contract Vault is ERC20, ERC20Detailed {
// using SafeERC20 for IERC20;
// using Address for address;
// using SafeMath for uint256;
// IERC20 public token;
// uint256 public min = 9500;
// uint256 public constant max = 10000;
// address public governance;
// address public controller;
// constructor (
// address _token,
// address _controller,
// address _governance
// )
// public
// ERC20Detailed(
// string(
// abi.encodePacked("Stake DAO ", ERC20Detailed(_token).name())
// ),
// string(abi.encodePacked("sd", ERC20Detailed(_token).symbol())),
// ERC20Detailed(_token).decimals()
// )
// {
// token = IERC20(_token);
// controller = _controller;
// governance = _governance;
// }
// function balance() public view returns (uint256) {
// return
// token.balanceOf(address(this)).add(
// IController(controller).balanceOf(address(token))
// );
// }
// function setMin(uint256 _min) external {
// require(msg.sender == governance, "!governance");
// min = _min;
// }
// function setGovernance(address _governance) public {
// require(msg.sender == governance, "!governance");
// governance = _governance;
// }
// function setController(address _controller) public {
// require(msg.sender == governance, "!governance");
// controller = _controller;
// }
// // Custom logic in here for how much the vault allows to be borrowed
// // Sets minimum required on-hand to keep small withdrawals cheap
// function available() public view returns (uint256) {
// return token.balanceOf(address(this)).mul(min).div(max);
// }
// function earn() public {
// uint256 _bal = available();
// token.safeTransfer(controller, _bal);
// IController(controller).earn(address(token), _bal);
// }
// function depositAll() external {
// deposit(token.balanceOf(msg.sender));
// }
// function deposit(uint256 _amount) public {
// uint256 _pool = balance();
// uint256 _before = token.balanceOf(address(this));
// token.safeTransferFrom(msg.sender, address(this), _amount);
// uint256 _after = token.balanceOf(address(this));
// _amount = _after.sub(_before); // Additional check for deflationary tokens
// uint256 shares = 0;
// if (totalSupply() == 0) {
// shares = _amount;
// } else {
// shares = (_amount.mul(totalSupply())).div(_pool);
// }
// _mint(msg.sender, shares);
// }
// function withdrawAll() external {
// withdraw(balanceOf(msg.sender));
// }
// // Used to swap any borrowed reserve over the debt limit to liquidate to 'token'
// function harvest(address reserve, uint256 amount) external {
// require(msg.sender == controller, "!controller");
// require(reserve != address(token), "token");
// IERC20(reserve).safeTransfer(controller, amount);
// }
// // No rebalance implementation for lower fees and faster swaps
// function withdraw(uint256 _shares) public {
// uint256 r = (balance().mul(_shares)).div(totalSupply());
// _burn(msg.sender, _shares);
// // Check balance
// uint256 b = token.balanceOf(address(this));
// if (b < r) {
// uint256 _withdraw = r.sub(b);
// IController(controller).withdraw(address(token), _withdraw);
// uint256 _after = token.balanceOf(address(this));
// uint256 _diff = _after.sub(b);
// if (_diff < _withdraw) {
// r = b.add(_diff);
// }
// }
// token.safeTransfer(msg.sender, r);
// }
// function getPricePerFullShare() public view returns (uint256) {
// return
// totalSupply() == 0 ? 1e18 : balance().mul(1e18).div(totalSupply());
// }
// }
// 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/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/Staking/StakingRewardsMultiGauge.sol
pragma experimental ABIEncoderV2;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ===================== StakingRewardsMultiGauge =====================
// ====================================================================
// veFXS-enabled
// Multiple tokens with different reward rates can be emitted
// Multiple teams can set the reward rates for their token(s)
// Those teams can also use a gauge, or an external function with
// 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
// Saddle Team: https://github.com/saddle-finance
// Fei Team: https://github.com/fei-protocol
// Alchemix Team: https://github.com/alchemix-finance
// Liquity Team: https://github.com/liquity
// Originally inspired by Synthetix.io, but heavily modified by the Frax team
// https://raw.githubusercontent.com/Synthetixio/synthetix/develop/contracts/StakingRewards.sol
// -------------------- VARIES --------------------
// mStable
// import '../Misc_AMOs/mstable/IFeederPool.sol';
// StakeDAO
// import '../Curve/IMetaImplementationUSD.sol';
// Uniswap V2
// import '../Uniswap/Interfaces/IUniswapV2Pair.sol';
// ------------------------------------------------
// Inheritance
contract StakingRewardsMultiGauge is Owned, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for ERC20;
/* ========== STATE VARIABLES ========== */
// Instances
IveFXS private veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0);
// -------------------- VARIES --------------------
// mStable
// IFeederPool public stakingToken;
// StakeDAO Vault
IStakeDaoVault public stakingToken;
// Uniswap V2
// IUniswapV2Pair public stakingToken;
// ------------------------------------------------
IFraxGaugeFXSRewardsDistributor public rewards_distributor;
// FRAX
address private constant frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e;
// Constant for various precisions
uint256 private 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_min = 86400; // 1 * 86400 (1 day)
// veFXS related
uint256 public vefxs_per_frax_for_max_boost = uint256(4e18); // E18. 4e18 means 4 veFXS must be held by the staker per 1 FRAX
uint256 public vefxs_max_multiplier = uint256(2e18); // E18. 1x = 1e18
mapping(address => uint256) private _vefxsMultiplierStored;
// Reward addresses, gauge addresses, reward rates, and reward managers
mapping(address => address) public rewardManagers; // token addr -> manager addr
address[] public rewardTokens;
address[] public gaugeControllers;
uint256[] public rewardRatesManual;
string[] public rewardSymbols;
mapping(address => uint256) public rewardTokenAddrToIdx; // token addr -> token index
// Reward period
uint256 public 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) private lastRewardClaimTime; // staker addr -> timestamp
uint256[] private last_gauge_relative_weights;
uint256[] private last_gauge_time_totals;
// Balance tracking
uint256 private _total_liquidity_locked;
uint256 private _total_combined_weight;
mapping(address => uint256) private _locked_liquidity;
mapping(address => uint256) private _combined_weights;
// List of valid migrators (set by governance)
mapping(address => bool) public valid_migrators;
// Stakers set which migrator(s) they want to use
mapping(address => mapping(address => bool)) public staker_allowed_migrators;
// Uniswap V2 ONLY
bool frax_is_token0;
// Stake tracking
mapping(address => LockedStake[]) private lockedStakes;
// Greylisting of bad addresses
mapping(address => bool) public greylist;
// Administrative booleans
bool public stakesUnlocked; // Release locked stakes in case of emergency
bool public migrationsOn; // Used for migrations. Prevents new stakes, but allows LP and reward withdrawals
bool public withdrawalsPaused; // For emergencies
bool public rewardsCollectionPaused; // For emergencies
bool public stakingPaused; // For emergencies
/* ========== STRUCTS ========== */
struct LockedStake {
bytes32 kek_id;
uint256 start_timestamp;
uint256 liquidity;
uint256 ending_timestamp;
uint256 lock_multiplier; // 6 decimals of precision. 1x = 1000000
}
/* ========== MODIFIERS ========== */
modifier onlyByOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
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 notStakingPaused() {
require(stakingPaused == false, "Staking paused");
_;
}
modifier updateRewardAndBalance(address account, bool sync_too) {
_updateRewardAndBalance(account, sync_too);
_;
}
/* ========== CONSTRUCTOR ========== */
constructor (
address _owner,
address _stakingToken,
address _rewards_distributor_address,
string[] memory _rewardSymbols,
address[] memory _rewardTokens,
address[] memory _rewardManagers,
uint256[] memory _rewardRatesManual,
address[] memory _gaugeControllers
) Owned(_owner){
// -------------------- VARIES --------------------
// mStable
// stakingToken = IFeederPool(_stakingToken);
// StakeDAO
stakingToken = IStakeDaoVault(_stakingToken);
// Uniswap V2
// stakingToken = IUniswapV2Pair(_stakingToken);
// address token0 = stakingToken.token0();
// if (token0 == frax_address) frax_is_token0 = true;
// else frax_is_token0 = false;
// ------------------------------------------------
rewards_distributor = IFraxGaugeFXSRewardsDistributor(_rewards_distributor_address);
rewardTokens = _rewardTokens;
gaugeControllers = _gaugeControllers;
rewardRatesManual = _rewardRatesManual;
rewardSymbols = _rewardSymbols;
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.add(rewardsDuration);
}
/* ========== VIEWS ========== */
// Total locked liquidity tokens
function totalLiquidityLocked() external view returns (uint256) {
return _total_liquidity_locked;
}
// Locked liquidity for a given account
function lockedLiquidityOf(address account) external view returns (uint256) {
return _locked_liquidity[account];
}
// Total 'balance' used for calculating the percent of the pool the account owns
// Takes into account the locked stake time multiplier
function totalCombinedWeight() external view returns (uint256) {
return _total_combined_weight;
}
// Combined weight for a specific account
function combinedWeightOf(address account) external view returns (uint256) {
return _combined_weights[account];
}
function fraxPerLPToken() public view returns (uint256) {
// Get the amount of FRAX 'inside' of the lp tokens
uint256 frax_per_lp_token;
// // Uniswap V2
// // ============================================
// {
// uint256 total_frax_reserves;
// (uint256 reserve0, uint256 reserve1, ) = (stakingToken.getReserves());
// if (frax_is_token0) total_frax_reserves = reserve0;
// else total_frax_reserves = reserve1;
// frax_per_lp_token = total_frax_reserves.mul(1e18).div(stakingToken.totalSupply());
// }
// // mStable
// // ============================================
// {
// uint256 total_frax_reserves;
// (, IFeederPool.BassetData memory vaultData) = (stakingToken.getBasset(frax_address));
// total_frax_reserves = uint256(vaultData.vaultBalance);
// frax_per_lp_token = total_frax_reserves.mul(1e18).div(stakingToken.totalSupply());
// }
// StakeDAO
// ============================================
{
uint256 frax3crv_held = stakingToken.balance();
// Optimistically assume 50/50 FRAX/3CRV ratio in the metapool to save gas
frax_per_lp_token = frax3crv_held.mul(1e18).div(stakingToken.totalSupply()) / 2;
}
return frax_per_lp_token;
}
function userStakedFrax(address account) public view returns (uint256) {
return (fraxPerLPToken()).mul(_locked_liquidity[account]).div(1e18);
}
function minVeFXSForMaxBoost(address account) public view returns (uint256) {
return (userStakedFrax(account)).mul(vefxs_per_frax_for_max_boost).div(MULTIPLIER_PRECISION);
}
function veFXSMultiplier(address account) public view returns (uint256) {
// The claimer gets a boost depending on amount of veFXS they have relative to the amount of FRAX 'inside'
// of their locked LP tokens
uint256 veFXS_needed_for_max_boost = minVeFXSForMaxBoost(account);
if (veFXS_needed_for_max_boost > 0){
uint256 user_vefxs_fraction = (veFXS.balanceOf(account)).mul(MULTIPLIER_PRECISION).div(veFXS_needed_for_max_boost);
uint256 vefxs_multiplier = ((user_vefxs_fraction).mul(vefxs_max_multiplier)).div(MULTIPLIER_PRECISION);
// Cap the boost to the vefxs_max_multiplier
if (vefxs_multiplier > vefxs_max_multiplier) vefxs_multiplier = vefxs_max_multiplier;
return vefxs_multiplier;
}
else return 0; // This will happen with the first stake, when user_staked_frax is 0
}
// Calculated the combined weight for an account
function calcCurCombinedWeight(address account) public 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).add(_vefxsMultiplierStored[account])).div(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).sub(lastRewardClaimTime[account]);
uint256 time_after_expiry = (block.timestamp).sub(thisStake.ending_timestamp);
// Get the weighted-average lock_multiplier
uint256 numerator = ((lock_multiplier).mul(time_before_expiry)).add(((MULTIPLIER_PRECISION).mul(time_after_expiry)));
lock_multiplier = numerator.div(time_before_expiry.add(time_after_expiry));
}
// Otherwise, it needs to just be 1x
else {
lock_multiplier = MULTIPLIER_PRECISION;
}
}
uint256 liquidity = thisStake.liquidity;
uint256 combined_boosted_amount = liquidity.mul(lock_multiplier.add(midpoint_vefxs_multiplier)).div(MULTIPLIER_PRECISION);
new_combined_weight = new_combined_weight.add(combined_boosted_amount);
}
}
// All the locked stakes for a given account
function lockedStakesOf(address account) external view returns (LockedStake[] memory) {
return lockedStakes[account];
}
// All the locked stakes for a given account
function getRewardSymbols() external view returns (string[] memory) {
return rewardSymbols;
}
// All the reward tokens
function getAllRewardTokens() external view returns (address[] memory) {
return rewardTokens;
}
// Multiplier amount, given the length of the lock
function lockMultiplier(uint256 secs) public view returns (uint256) {
uint256 lock_multiplier =
uint256(MULTIPLIER_PRECISION).add(
secs
.mul(lock_max_multiplier.sub(MULTIPLIER_PRECISION))
.div(lock_time_for_max_multiplier)
);
if (lock_multiplier > lock_max_multiplier) lock_multiplier = lock_max_multiplier;
return lock_multiplier;
}
// 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()).mul(last_gauge_relative_weights[token_idx]).div(1e18);
}
else {
rwd_rate = rewardRatesManual[token_idx];
}
}
// Amount of reward tokens per LP token
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].add(
lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRates(i)).mul(1e18).div(_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] = 0;
}
}
else {
for (uint256 i = 0; i < rewardTokens.length; i++){
new_earned[i] = (_combined_weights[account])
.mul(reward_arr[i].sub(userRewardsPerTokenPaid[account][i]))
.div(1e18)
.add(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).mul(rewardsDuration);
}
}
// 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;
}
/* ========== MUTATIVE FUNCTIONS ========== */
// Staker can allow a migrator
function stakerAllowMigrator(address migrator_address) external {
require(valid_migrators[migrator_address], "Invalid migrator address");
staker_allowed_migrators[msg.sender][migrator_address] = true;
}
// Staker can disallow a previously-allowed migrator
function stakerDisallowMigrator(address migrator_address) external {
// Delete from the mapping
delete staker_allowed_migrators[msg.sender][migrator_address];
}
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.sub(old_combined_weight);
_total_combined_weight = _total_combined_weight.add(weight_diff);
_combined_weights[account] = old_combined_weight.add(weight_diff);
} else {
uint256 weight_diff = old_combined_weight.sub(new_combined_weight);
_total_combined_weight = _total_combined_weight.sub(weight_diff);
_combined_weights[account] = old_combined_weight.sub(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];
}
}
}
// Two different stake functions are needed because of delegateCall and msg.sender issues
function stakeLocked(uint256 liquidity, uint256 secs) nonReentrant public {
_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) {
require(!stakingPaused, "Staking paused");
require(liquidity > 0, "Must stake more than zero");
require(greylist[staker_address] == false, "Address has been greylisted");
require(secs >= lock_time_min, "Minimum stake time not met");
require(secs <= lock_time_for_max_multiplier,"Trying to lock for too long");
uint256 lock_multiplier = lockMultiplier(secs);
bytes32 kek_id = keccak256(abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address]));
lockedStakes[staker_address].push(LockedStake(
kek_id,
start_timestamp,
liquidity,
start_timestamp.add(secs),
lock_multiplier
));
// Pull the tokens from the source_address
TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity);
// Update liquidities
_total_liquidity_locked = _total_liquidity_locked.add(liquidity);
_locked_liquidity[staker_address] = _locked_liquidity[staker_address].add(liquidity);
// Need to call to update the combined weights
_updateRewardAndBalance(staker_address, false);
// Needed for edge case if the staker only claims once, and after the lock expired
if (lastRewardClaimTime[staker_address] == 0) lastRewardClaimTime[staker_address] = block.timestamp;
emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address);
}
// Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues
function withdrawLocked(bytes32 kek_id) nonReentrant public {
require(withdrawalsPaused == false, "Withdrawals paused");
_withdrawLocked(msg.sender, msg.sender, kek_id);
}
// No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper
// functions like withdraw(), migrator_withdraw_unlocked() and migrator_withdraw_locked()
function _withdrawLocked(address staker_address, address destination_address, bytes32 kek_id) internal {
// Collect rewards first and then update the balances
_getReward(staker_address, destination_address);
LockedStake memory thisStake;
thisStake.liquidity = 0;
uint theArrayIndex;
for (uint256 i = 0; i < lockedStakes[staker_address].length; i++){
if (kek_id == lockedStakes[staker_address][i].kek_id){
thisStake = lockedStakes[staker_address][i];
theArrayIndex = i;
break;
}
}
require(thisStake.kek_id == kek_id, "Stake not found");
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 = _total_liquidity_locked.sub(liquidity);
_locked_liquidity[staker_address] = _locked_liquidity[staker_address].sub(liquidity);
// Remove the stake from the array
delete lockedStakes[staker_address][theArrayIndex];
// Need to call to update the combined weights
_updateRewardAndBalance(staker_address, false);
// Give the tokens to the destination_address
// Should throw if insufficient balance
stakingToken.transfer(destination_address, liquidity);
emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address);
}
}
// Two different getReward functions are needed because of delegateCall and msg.sender issues
function getReward() external nonReentrant returns (uint256[] memory) {
require(rewardsCollectionPaused == false,"Rewards collection paused");
return _getReward(msg.sender, msg.sender);
}
// No withdrawer == msg.sender check needed since this is only internally callable
function _getReward(address rewardee, address destination_address) internal updateRewardAndBalance(rewardee, true) returns (uint256[] memory rewards_before) {
// 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;
ERC20(rewardTokens[i]).transfer(destination_address, rewards_before[i]);
emit RewardPaid(rewardee, rewards_before[i], rewardTokens[i], destination_address);
}
lastRewardClaimTime[rewardee] = block.timestamp;
}
// If the period expired, renew it
function retroCatchUp() internal {
// Pull in rewards from the rewards distributor
rewards_distributor.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.sub(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).mul(rewardsDuration).mul(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.add((num_periods_elapsed.add(1)).mul(rewardsDuration));
_updateStoredRewardsAndTime();
emit RewardsPeriodRenewed(address(stakingToken));
}
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);
if (block.timestamp >= periodFinish) {
retroCatchUp();
}
else {
_updateStoredRewardsAndTime();
}
}
/* ========== RESTRICTED FUNCTIONS ========== */
// 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);
}
// Adds supported migrator address
function addMigrator(address migrator_address) external onlyByOwner {
valid_migrators[migrator_address] = true;
}
// Remove a migrator address
function removeMigrator(address migrator_address) external onlyByOwner {
require(valid_migrators[migrator_address] == true, "Address nonexistant");
// Delete from the mapping
delete valid_migrators[migrator_address];
}
// 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
if (isRewardToken && rewardManagers[tokenAddress] == msg.sender){
ERC20(tokenAddress).transfer(msg.sender, tokenAmount);
emit Recovered(msg.sender, tokenAddress, tokenAmount);
return;
}
// Other tokens, like the staking token, airdrops, or accidental deposits, can be withdrawn by the owner
else if (!isRewardToken && (msg.sender == owner)){
ERC20(tokenAddress).transfer(msg.sender, tokenAmount);
emit Recovered(msg.sender, tokenAddress, tokenAmount);
return;
}
// If none of the above conditions are true
else {
revert("No valid tokens to recover");
}
}
function setRewardsDuration(uint256 _rewardsDuration) external onlyByOwner {
require(_rewardsDuration >= 86400, "Rewards duration too short");
require(
periodFinish == 0 || block.timestamp > periodFinish,
"Reward period incomplete"
);
rewardsDuration = _rewardsDuration;
emit RewardsDurationUpdated(rewardsDuration);
}
function setMultipliers(uint256 _lock_max_multiplier, uint256 _vefxs_max_multiplier, uint256 _vefxs_per_frax_for_max_boost) external onlyByOwner {
require(_lock_max_multiplier >= MULTIPLIER_PRECISION, "Mult must be >= MULTIPLIER_PRECISION");
require(_vefxs_max_multiplier >= 0, "veFXS mul must be >= 0");
require(_vefxs_per_frax_for_max_boost > 0, "veFXS pct max must be >= 0");
lock_max_multiplier = _lock_max_multiplier;
vefxs_max_multiplier = _vefxs_max_multiplier;
vefxs_per_frax_for_max_boost = _vefxs_per_frax_for_max_boost;
emit MaxVeFXSMultiplier(vefxs_max_multiplier);
emit LockedStakeMaxMultiplierUpdated(lock_max_multiplier);
emit veFXSPerFraxForMaxBoostUpdated(vefxs_per_frax_for_max_boost);
}
function setLockedStakeTimeForMinAndMaxMultiplier(uint256 _lock_time_for_max_multiplier, uint256 _lock_time_min) external onlyByOwner {
require(_lock_time_for_max_multiplier >= 1, "Mul max time must be >= 1");
require(_lock_time_min >= 1, "Mul min time must be >= 1");
lock_time_for_max_multiplier = _lock_time_for_max_multiplier;
lock_time_min = _lock_time_min;
emit LockedStakeTimeForMaxMultiplier(lock_time_for_max_multiplier);
emit LockedStakeMinTime(_lock_time_min);
}
function greylistAddress(address _address) external onlyByOwner {
greylist[_address] = !(greylist[_address]);
}
function unlockStakes() external onlyByOwner {
stakesUnlocked = !stakesUnlocked;
}
function toggleStaking() external onlyByOwner {
stakingPaused = !stakingPaused;
}
function toggleMigrations() external onlyByOwner {
migrationsOn = !migrationsOn;
}
function toggleWithdrawals() external onlyByOwner {
withdrawalsPaused = !withdrawalsPaused;
}
function toggleRewardsCollection() external onlyByOwner {
rewardsCollectionPaused = !rewardsCollectionPaused;
}
// The owner or the reward token managers can set reward rates
function setRewardRate(address reward_token_address, uint256 new_rate, bool sync_too) external onlyTknMgrs(reward_token_address) {
rewardRatesManual[rewardTokenAddrToIdx[reward_token_address]] = new_rate;
if (sync_too){
sync();
}
}
// The owner or the reward token managers can set reward rates
function setGaugeController(address reward_token_address, address _rewards_distributor_address, address _gauge_controller_address, bool sync_too) external onlyTknMgrs(reward_token_address) {
gaugeControllers[rewardTokenAddrToIdx[reward_token_address]] = _gauge_controller_address;
rewards_distributor = IFraxGaugeFXSRewardsDistributor(_rewards_distributor_address);
if (sync_too){
sync();
}
}
// 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;
}
/* ========== EVENTS ========== */
event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address);
event WithdrawLocked(address indexed user, uint256 amount, bytes32 kek_id, address destination_address);
event RewardPaid(address indexed user, uint256 reward, address token_address, address destination_address);
event RewardsDurationUpdated(uint256 newDuration);
event Recovered(address destination_address, address token, uint256 amount);
event RewardsPeriodRenewed(address token);
event LockedStakeMaxMultiplierUpdated(uint256 multiplier);
event LockedStakeTimeForMaxMultiplier(uint256 secs);
event LockedStakeMinTime(uint256 secs);
event MaxVeFXSMultiplier(uint256 multiplier);
event veFXSPerFraxForMaxBoostUpdated(uint256 scale_factor);
}
// File contracts/Staking/Variants/StakingRewardsMultiGauge_StakeDAO.sol
contract StakingRewardsMultiGauge_StakeDAO is StakingRewardsMultiGauge {
constructor (
address _owner,
address _stakingToken,
address _rewards_distributor_address,
string[] memory _rewardSymbols,
address[] memory _rewardTokens,
address[] memory _rewardManagers,
uint256[] memory _rewardRates,
address[] memory _gaugeControllers
)
StakingRewardsMultiGauge(_owner, _stakingToken, _rewards_distributor_address, _rewardSymbols, _rewardTokens, _rewardManagers, _rewardRates, _gaugeControllers)
{}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_rewards_distributor_address","type":"address"},{"internalType":"string[]","name":"_rewardSymbols","type":"string[]"},{"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"internalType":"address[]","name":"_rewardManagers","type":"address[]"},{"internalType":"uint256[]","name":"_rewardRates","type":"uint256[]"},{"internalType":"address[]","name":"_gaugeControllers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"LockedStakeMaxMultiplierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"secs","type":"uint256"}],"name":"LockedStakeMinTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"secs","type":"uint256"}],"name":"LockedStakeTimeForMaxMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"MaxVeFXSMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destination_address","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"address","name":"token_address","type":"address"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"RewardsDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"RewardsPeriodRenewed","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"WithdrawLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"scale_factor","type":"uint256"}],"name":"veFXSPerFraxForMaxBoostUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_address","type":"address"}],"name":"addMigrator","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":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"new_earned","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"gaugeControllers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256[]","name":"rewards_per_duration_arr","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardSymbols","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"greylist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"greylistAddress","outputs":[],"stateMutability":"nonpayable","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":"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":"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 StakingRewardsMultiGauge.LockedStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrationsOn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"_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":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_address","type":"address"}],"name":"removeMigrator","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":"uint256","name":"","type":"uint256"}],"name":"rewardRatesManual","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardSymbols","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsCollectionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"rewards_distributor","outputs":[{"internalType":"contract IFraxGaugeFXSRewardsDistributor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"address","name":"_rewards_distributor_address","type":"address"},{"internalType":"address","name":"_gauge_controller_address","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"setGaugeController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lock_time_for_max_multiplier","type":"uint256"},{"internalType":"uint256","name":"_lock_time_min","type":"uint256"}],"name":"setLockedStakeTimeForMinAndMaxMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lock_max_multiplier","type":"uint256"},{"internalType":"uint256","name":"_vefxs_max_multiplier","type":"uint256"},{"internalType":"uint256","name":"_vefxs_per_frax_for_max_boost","type":"uint256"}],"name":"setMultipliers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"uint256","name":"new_rate","type":"uint256"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"setRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"stakeLocked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_address","type":"address"}],"name":"stakerAllowMigrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_address","type":"address"}],"name":"stakerDisallowMigrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"staker_allowed_migrators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakesUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IStakeDaoVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"force_update","type":"bool"}],"name":"sync_gauge_weights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMigrations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleRewardsCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleWithdrawals","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":"","type":"address"}],"name":"valid_migrators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"veFXSMultiplier","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"}],"name":"withdrawLocked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6080604052600380546001600160a01b03191673c8418af6358ffdda74e09ca9cc3fe03ca6adc5b01790556729a2241af62c00006008556305a39a8060095562015180600a55673782dace9d900000600b55671bc16d674ec80000600c5562093a806014553480156200007157600080fd5b5060405162005c2638038062005c26833981016040819052620000949162000817565b8787878787878787876001600160a01b038116620000f95760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1506001600255600480546001600160a01b03808a166001600160a01b031992831617909255600580549289169290911691909117905583516200019b90600f906020870190620003f8565b508051620001b1906010906020840190620003f8565b508151620001c790601190602085019062000462565b508451620001dd906012906020880190620004a0565b5060005b84518110156200034857806013600087848151811062000205576200020562000a16565b6020908102919091018101516001600160a01b03168252810191909152604001600090812091909155601580546001810182559082527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec4750155835184908290811062000275576200027562000a16565b6020026020010151600e600087848151811062000296576200029662000a16565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b031916939092169290921790556019805460018181019092557f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969501829055601a8054918201815582527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e0155806200033f81620009e2565b915050620001e1565b506024805460ff191690554260078190556014546200037491906200038e602090811b6200358617901c565b6006555062000a429e505050505050505050505050505050565b6000806200039d83856200098a565b905083811015620003f15760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401620000f0565b9392505050565b82805482825590600052602060002090810192821562000450579160200282015b828111156200045057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000419565b506200045e92915062000500565b5090565b82805482825590600052602060002090810192821562000450579160200282015b828111156200045057825182559160200191906001019062000483565b828054828255906000526020600020908101928215620004f2579160200282015b82811115620004f25782518051620004e191849160209091019062000517565b5091602001919060010190620004c1565b506200045e92915062000593565b5b808211156200045e576000815560010162000501565b8280546200052590620009a5565b90600052602060002090601f01602090048101928262000549576000855562000450565b82601f106200056457805160ff191683800117855562000450565b828001600101855582156200045057918201828111156200045057825182559160200191906001019062000483565b808211156200045e576000620005aa8282620005b4565b5060010162000593565b508054620005c290620009a5565b6000825580601f10620005d3575050565b601f016020900490600052602060002090810190620005f3919062000500565b50565b80516001600160a01b03811681146200060e57600080fd5b919050565b600082601f8301126200062557600080fd5b815160206200063e620006388362000964565b62000931565b80838252828201915082860187848660051b89010111156200065f57600080fd5b60005b8581101562000689576200067682620005f6565b8452928401929084019060010162000662565b5090979650505050505050565b6000601f8381840112620006a957600080fd5b82516020620006bc620006388362000964565b80838252828201915082870188848660051b8a01011115620006dd57600080fd5b60005b85811015620007a25781516001600160401b03808211156200070157600080fd5b818b0191508b603f8301126200071657600080fd5b86820151818111156200072d576200072d62000a2c565b62000740818b01601f1916890162000931565b915080825260408d818386010111156200075957600080fd5b60005b8281101562000779578481018201518482018b015289016200075c565b828111156200078b5760008a84860101525b5050508552509284019290840190600101620006e0565b509098975050505050505050565b600082601f830112620007c257600080fd5b81516020620007d5620006388362000964565b80838252828201915082860187848660051b8901011115620007f657600080fd5b60005b858110156200068957815184529284019290840190600101620007f9565b600080600080600080600080610100898b0312156200083557600080fd5b6200084089620005f6565b97506200085060208a01620005f6565b96506200086060408a01620005f6565b60608a01519096506001600160401b03808211156200087e57600080fd5b6200088c8c838d0162000696565b965060808b0151915080821115620008a357600080fd5b620008b18c838d0162000613565b955060a08b0151915080821115620008c857600080fd5b620008d68c838d0162000613565b945060c08b0151915080821115620008ed57600080fd5b620008fb8c838d01620007b0565b935060e08b01519150808211156200091257600080fd5b50620009218b828c0162000613565b9150509295985092959890939650565b604051601f8201601f191681016001600160401b03811182821017156200095c576200095c62000a2c565b604052919050565b60006001600160401b0382111562000980576200098062000a2c565b5060051b60200190565b60008219821115620009a057620009a062000a00565b500190565b600181811c90821680620009ba57607f821691505b60208210811415620009dc57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415620009f957620009f962000a00565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6151d48062000a526000396000f3fe608060405234801561001057600080fd5b50600436106104715760003560e01c806379ba509711610250578063cdc82e8011610150578063ebe2b12b116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a61578063fce6fd1314610a74578063fff6cae914610a8657600080fd5b8063f2a8d34914610a45578063f2caeb1e14610a4e57600080fd5b8063ebe2b12b146109fd578063ee89e02f14610a06578063f12f144714610a29578063f288baf614610a3c57600080fd5b8063de1a65511161011f578063e1ba95d211610104578063e1ba95d2146109cf578063e9f2838e146109d7578063eb3c209e146109ea57600080fd5b8063de1a6551146109b4578063e01f62bf146109c757600080fd5b8063cdc82e801461095a578063d239f00314610963578063d42fc9b41461096b578063d9f96e8d1461097e57600080fd5b80639637927f116101e3578063af00f4e2116101b2578063bbb781cc11610197578063bbb781cc14610929578063c8f33c911461093e578063cc1a378f1461094757600080fd5b8063af00f4e21461090d578063b94c4dcb1461092057600080fd5b80639637927f146108b95780639b8c15a8146108c65780639c5303eb146108f2578063a2217bc51461090557600080fd5b80638980f11f1161021f5780638980f11f146108455780638bad86a7146108585780638da5cb5b14610886578063941d9f65146108a657600080fd5b806379ba50971461080f5780637a2ae103146108175780637b31c19a1461082a5780637bb7bed11461083257600080fd5b8063386a9525116103765780635bfd9258116102ee57806369339245116102bd5780636e27cef9116102a25780636e27cef9146107de57806370641a36146107e757806372f702f3146107ef57600080fd5b806369339245146107ab5780636ce46bc3146107cb57600080fd5b80635bfd92581461077357806364f2c0601461077b57806366b237d01461078357806366e9e9b31461079657600080fd5b806349fb388a1161034557806351e3fc171161032a57806351e3fc17146106db57806352732bc8146106ee57806353a47bb71461075357600080fd5b806349fb388a146106a85780634fd2b536146106c857600080fd5b8063386a9525146106595780633b8105b3146106625780633d18b9121461066a57806341a16f3f1461067257600080fd5b80631e090f011161040957806328ef934e116103d857806331ca208c116103bd57806331ca208c146105ec578063323331ca1461060f57806336f89af21461062357600080fd5b806328ef934e146105c65780632c0c2a0a146105d957600080fd5b80631e090f01146105505780631e368980146105705780631f5848de14610590578063231b68dc146105a357600080fd5b806317b18c891161044557806317b18c89146104ea5780631b3e870a146104fd5780631c1f78eb146105105780631c56f33e1461051857600080fd5b80628cc262146104765780630d7bac4f1461049f57806312edb24c146104c05780631627540c146104d5575b600080fd5b610489610484366004614b8b565b610a8e565b6040516104969190614f5e565b60405180910390f35b6104b26104ad366004614d0c565b610c59565b604051908152602001610496565b6104c8610cb2565b6040516104969190614e16565b6104e86104e3366004614b8b565b610d21565b005b6104e86104f8366004614d3e565b610e47565b6104e861050b366004614b8b565b610ecd565b61048961102e565b61052b610526366004614d0c565b6110cd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610496565b61056361055e366004614b8b565b611104565b6040516104969190614ef0565b61058361057e366004614d0c565b6111b8565b6040516104969190614f96565b6104e861059e366004614c59565b611264565b6105b66105b1366004614ba6565b611352565b6040519015158152602001610496565b6104e86105d4366004614c99565b6113c1565b6104b26105e7366004614b8b565b6114f8565b6105b66105fa366004614b8b565b60236020526000908152604090205460ff1681565b6024546105b6906301000000900460ff1681565b6104b2610631366004614b8b565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104b260145481565b6104e8611603565b6104896116c1565b61052b610680366004614b8b565b600e6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60055461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26106d6366004614b8b565b6117bb565b6104e86106e9366004614d0c565b6117d8565b6104e86106fc366004614b8b565b3360009081526020808052604080832073ffffffffffffffffffffffffffffffffffffffff9490941683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60015461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26118ce565b601c546104b2565b6104b2610791366004614d0c565b611a3d565b61079e611a5e565b6040516104969190614e70565b6104b26107b9366004614b8b565b60136020526000908152604090205481565b6104e86107d9366004614d84565b611b37565b6104b2600a5481565b610489611d76565b60045461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104e8611ec7565b6104e8610825366004614bd9565b612012565b6104e8612152565b61052b610840366004614d0c565b61220f565b6104e8610853366004614c2f565b61221f565b61086b610866366004614b8b565b612554565b60408051938452602084019290925290820152606001610496565b60005461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104e86108b4366004614b8b565b612815565b6024546105b69060ff1681565b6105b66108d4366004614ba6565b60208080526000928352604080842090915290825290205460ff1681565b6104e8610900366004614b8b565b6128ea565b6104e86129ba565b6104e861091b366004614d3e565b612a75565b6104b260095481565b6024546105b690640100000000900460ff1681565b6104b260075481565b6104e8610955366004614d0c565b612c40565b6104b260085481565b6104e8612dd9565b6104b2610979366004614b8b565b612e95565b6104b261098c366004614b8b565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b6104e86109c2366004614ba6565b612ed5565b601b546104b2565b6104e8612fbc565b6024546105b69062010000900460ff1681565b6104e86109f8366004614c2f565b61306f565b6104b260065481565b6105b6610a14366004614b8b565b601f6020526000908152604090205460ff1681565b6104e8610a37366004614b8b565b6131a8565b6104b2600c5481565b6104b2600b5481565b6104b2610a5c366004614d0c565b613291565b6104e8610a6f366004614cd2565b613371565b6024546105b690610100900460ff1681565b6104e8613561565b60606000610a9a611d76565b600f5490915067ffffffffffffffff811115610ab857610ab8615161565b604051908082528060200260200182016040528015610ae1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040902054909250610b535760005b600f54811015610b4d576000838281518110610b3057610b30615132565b602090810291909101015280610b45816150ca565b915050610b12565b50610c53565b60005b600f54811015610c515773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351610c229291610c1c91670de0b6b3a764000091610c1691610bea9190899089908110610bd457610bd4615132565b60200260200101516135ff90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602052604090205490613641565b906136f6565b90613586565b838281518110610c3457610c34615132565b602090810291909101015280610c49816150ca565b915050610b56565b505b50919050565b600080610c9b610c8c600954610c16610c85670de0b6b3a76400006008546135ff90919063ffffffff16565b8790613641565b670de0b6b3a764000090613586565b9050600854811115610cac57506008545b92915050565b6060600f805480602002602001604051908101604052809291908181526020018280548015610d1757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610cec575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b600280541415610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b60028055610ec43380848442613738565b50506001600255565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604090205460ff161515600114610fe2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60115460609067ffffffffffffffff81111561104c5761104c615161565b604051908082528060200260200182016040528015611075578160200160208202803683370190505b50905060005b6011548110156110c95761109a60145461109483613291565b90613641565b8282815181106110ac576110ac615132565b6020908102919091010152806110c1816150ca565b91505061107b565b5090565b601081815481106110dd57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602260209081526040808320805482518185028101850190935280835260609492939192909184015b828210156111ad57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190611149565b505050509050919050565b601281815481106111c857600080fd5b9060005260206000200160009150905080546111e39061507c565b80601f016020809104026020016040519081016040528092919081815260200182805461120f9061507c565b801561125c5780601f106112315761010080835404028352916020019161125c565b820191906000526020600020905b81548152906001019060200180831161123f57829003601f168201915b505050505081565b600054839073ffffffffffffffffffffffffffffffffffffffff1633148061129157506112913382611352565b6112f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205460118054859290811061133257611332615132565b600091825260209091200155811561134c5761134c613561565b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8481169116141561137e57506001610cac565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600e6020526040902054811690841614156113b857506001610cac565b50600092915050565b60245460ff610100909104161515600114611438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020808052604080832033845290915290205460ff1680156114855750336000908152601f602052604090205460ff165b6114eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610dc4565b61134c8433858585613738565b600080611504836117bb565b905080156113b8576003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526000926115c5928592610c1692670de0b6b3a7640000929116906370a082319060240160206040518083038186803b15801561158d57600080fd5b505afa1580156115a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110949190614d25565b905060006115ea670de0b6b3a7640000610c16600c548561364190919063ffffffff16565b9050600c548111156115fb5750600c545b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff81166401000000009182900460ff1615909102179055565b606060028054141561172f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b600280556024546301000000900460ff16156117a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610dc4565b6117b13333613c30565b9050600160025590565b6000610cac670de0b6b3a7640000610c16600b5461109486612e95565b600280541415611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b6002805560245462010000900460ff16156118bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610dc4565b6118c6333383613f07565b506001600255565b6000806000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561193b57600080fd5b505afa15801561194f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119739190614d25565b90506002611a2c600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1a9190614d25565b610c1684670de0b6b3a7640000613641565b611a369190614fc1565b9392505050565b60118181548110611a4d57600080fd5b600091825260209091200154905081565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015611b2e578382906000526020600020018054611aa19061507c565b80601f0160208091040260200160405190810160405280929190818152602001828054611acd9061507c565b8015611b1a5780601f10611aef57610100808354040283529160200191611b1a565b820191906000526020600020905b815481529060010190602001808311611afd57829003601f168201915b505050505081526020019060010190611a82565b50505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314611bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b670de0b6b3a7640000831015611c4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4d756c74206d757374206265203e3d204d554c5449504c4945525f505245434960448201527f53494f4e000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b60008111611cb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f766546585320706374206d6178206d757374206265203e3d20300000000000006044820152606401610dc4565b6008839055600c829055600b8190556040518281527fc9d56ccdd6b954d8d74700db074cc667054f8e33c1b8d23e97021d4c588a87619060200160405180910390a17fa1676084a9eea08c6f205b60799323b364a1bd8e10aba89f0fbd94cfbf68b5dd600854604051611d2e91815260200190565b60405180910390a17f58c7ececaeb4704a0039e0d22c1b618367f7a7b9a4e191ab9baed34898f63f2e600b54604051611d6991815260200190565b60405180910390a1505050565b6060601b5460001480611d895750601c54155b15611de3576015805480602002602001604051908101604052809291908181526020018280548015610d1757602002820191906000526020600020905b815481526020019060010190808311611dc6575050505050905090565b600f5467ffffffffffffffff811115611dfe57611dfe615161565b604051908082528060200260200182016040528015611e27578160200160208202803683370190505b50905060005b6015548110156110c957611e98611e6c601c54610c16670de0b6b3a7640000611094611e5887613291565b611094600754611e6661434f565b906135ff565b60158381548110611e7f57611e7f615132565b906000526020600020015461358690919063ffffffff16565b828281518110611eaa57611eaa615132565b602090810291909101015280611ebf816150ca565b915050611e2d565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610dc4565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061203f575061203f3382611352565b6120a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601360205260409020546010805485929081106120e0576120e0615132565b600091825260209091200180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560058054909116918616919091179055811561214b5761214b613561565b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146121d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff811663010000009182900460ff1615909102179055565b600f81815481106110dd57600080fd5b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061224c575061224c3382611352565b6122b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b6000805b600f5481101561232d578473ffffffffffffffffffffffffffffffffffffffff16600f82815481106122ea576122ea615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561231b576001915061232d565b80612325816150ca565b9150506122b6565b50808015612361575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600e60205260409020541633145b1561246a576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff85169063a9059cbb906044015b602060405180830381600087803b1580156123d557600080fd5b505af11580156123e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240d9190614cef565b506040805133815273ffffffffffffffffffffffffffffffffffffffff861660208201529081018490527ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b6489060600160405180910390a150505050565b8015801561248f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b156124ed576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff85169063a9059cbb906044016123bb565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610dc4565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080612585846114f8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d6020526040812054919350901580156125df575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b156125eb575081612626565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d602052604090205461262390600290610c16908690613586565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff861660009081526022602052604090205481101561280c5773ffffffffffffffffffffffffffffffffffffffff8616600090815260226020526040812080548390811061269157612691615132565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600081608001519050428260600151116127c057606082015173ffffffffffffffffffffffffffffffffffffffff891660009081526018602052604090205410156127b55773ffffffffffffffffffffffffffffffffffffffff88166000908152601860205260408120546060840151612757916135ff565b905060006127728460600151426135ff90919063ffffffff16565b9050600061279561278b670de0b6b3a764000084613641565b610c1c8686613641565b90506127ab6127a48484613586565b82906136f6565b93505050506127c0565b50670de0b6b3a76400005b604082015160006127e7670de0b6b3a7640000610c166127e0868a613586565b8590613641565b90506127f38782613586565b9650505050508080612804906150ca565b91505061262d565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff16600090815260236020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461296b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314612af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b6001821015612b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d756c206d61782074696d65206d757374206265203e3d2031000000000000006044820152606401610dc4565b6001811015612bcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d756c206d696e2074696d65206d757374206265203e3d2031000000000000006044820152606401610dc4565b6009829055600a8190556040518281527f0e3e3fae480c6f92291358a02bc83f04ee1971d5488596bffda7929d57ab470f9060200160405180910390a16040518181527f0534d208d75dfdbfacc1204745dd9b3c4c37e8cfc05eb5e8e3ae538aedb0a9fa9060200160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b62015180811015612d2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f52657761726473206475726174696f6e20746f6f2073686f72740000000000006044820152606401610dc4565b6006541580612d3e575060065442115b612da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52657761726420706572696f6420696e636f6d706c65746500000000000000006044820152606401610dc4565b60148190556040518181527ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d390602001610e3c565b60005473ffffffffffffffffffffffffffffffffffffffff163314612e5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff8116620100009182900460ff1615909102179055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054610cac90670de0b6b3a764000090610c16906110946118ce565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612f025750612f023382611352565b612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600e6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461303d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60245460ff6101009091041615156001146130e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020808052604080832033845290915290205460ff1680156131335750336000908152601f602052604090205460ff165b613199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610dc4565b6131a4823383613f07565b5050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604090205460ff16613237576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206d69677261746f72206164647265737300000000000000006044820152606401610dc4565b3360009081526020808052604080832073ffffffffffffffffffffffffffffffffffffffff9490941683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600080601083815481106132a7576132a7615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561334b57613344670de0b6b3a7640000610c16601986815481106132f3576132f3615132565b90600052602060002001548473ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b815260040160206040518083038186803b15801561158d57600080fd5b9150610c53565b6011838154811061335e5761335e615132565b9060005260206000200154915050919050565b60005b6010548110156131a45760006010828154811061339357613393615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561354e5782806133e55750601a82815481106133d7576133d7615132565b906000526020600020015442115b1561354e576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee190604401602060405180830381600087803b15801561345757600080fd5b505af115801561346b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348f9190614d25565b601983815481106134a2576134a2615132565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f657600080fd5b505afa15801561350a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352e9190614d25565b601a838154811061354157613541615132565b6000918252602090912001555b5080613559816150ca565b915050613374565b61356b6000613371565b600654421061357e5761357c614362565b565b61357c614682565b6000806135938385614fa9565b905083811015611a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610dc4565b6000611a3683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506146f5565b60008261365057506000610cac565b600061365c8385614ffc565b9050826136698583614fc1565b14611a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b6000611a3683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614749565b8460016137458282614791565b602454640100000000900460ff16156137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610dc4565b60008511613824576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d757374207374616b65206d6f7265207468616e207a65726f000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff871660009081526023602052604090205460ff16156138b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4164647265737320686173206265656e20677265796c697374656400000000006044820152606401610dc4565b600a54841015613920576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610dc4565b60095484111561398c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610dc4565b600061399785610c59565b73ffffffffffffffffffffffffffffffffffffffff89166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608e901b169281019290925260348201889052605482018a9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8d1660009081526022835283902060a0850184528185529184018990529183018a90529092509060608101613a8a888a613586565b815260209081018590528254600181810185556000948552938290208351600590920201908155908201519281019290925560408101516002830155606081015160038301556080015160049182015554613afd9073ffffffffffffffffffffffffffffffffffffffff1689308a6148b3565b601b54613b0a9088613586565b601b5573ffffffffffffffffffffffffffffffffffffffff89166000908152601d6020526040902054613b3d9088613586565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812091909155613b71908a90614791565b73ffffffffffffffffffffffffffffffffffffffff8916600090815260186020526040902054613bc45773ffffffffffffffffffffffffffffffffffffffff891660009081526018602052604090204290555b604080518881526020810188905290810182905273ffffffffffffffffffffffffffffffffffffffff89811660608301528a16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a2505050505050505050565b6060826001613c3f8282614791565b600f5467ffffffffffffffff811115613c5a57613c5a615161565b604051908082528060200260200182016040528015613c83578160200160208202803683370190505b50925060005b600f54811015613ed75773ffffffffffffffffffffffffffffffffffffffff861660009081526017602090815260408083208484529091529020548451859083908110613cd857613cd8615132565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8716600090815260178252604080822084835290925290812055600f805482908110613d2a57613d2a615132565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86868481518110613d8357613d83615132565b60200260200101516040518363ffffffff1660e01b8152600401613dc992919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381600087803b158015613de357600080fd5b505af1158015613df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e1b9190614cef565b508573ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613e6657613e66615132565b6020026020010151600f8481548110613e8157613e81615132565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff9182169284019290925289169082015260600160405180910390a280613ecf816150ca565b915050613c89565b50505073ffffffffffffffffffffffffffffffffffffffff90921660009081526018602052604090204290555090565b613f118383613c30565b50613f476040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600060408201819052805b73ffffffffffffffffffffffffffffffffffffffff861660009081526022602052604090205481101561406d5773ffffffffffffffffffffffffffffffffffffffff86166000908152602260205260409020805482908110613fb657613fb6615132565b90600052602060002090600502016000015484141561405b5773ffffffffffffffffffffffffffffffffffffffff8616600090815260226020526040902080548290811061400657614006615132565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050925080915061406d565b80614065816150ca565b915050613f52565b50815183146140d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610dc4565b8160600151421015806140f2575060245460ff1615156001145b806141115750336000908152601f602052604090205460ff1615156001145b614177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610dc4565b6040820151801561434757601b5461418f90826135ff565b601b5573ffffffffffffffffffffffffffffffffffffffff86166000908152601d60205260409020546141c290826135ff565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601d6020908152604080832093909355602290522080548390811061420557614205615132565b60009182526020822060059091020181815560018101829055600281018290556003810182905560040181905561423d908790614791565b600480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116938201939093526024810184905291169063a9059cbb90604401602060405180830381600087803b1580156142b357600080fd5b505af11580156142c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142eb9190614cef565b50604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff878116828401529151918816917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b505050505050565b600061435d42600654614a49565b905090565b6005546040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169063092193ab906024016040805180830381600087803b1580156143cc57600080fd5b505af11580156143e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144049190614d60565b50506000601454614420600654426135ff90919063ffffffff16565b61442a9190614fc1565b905060005b600f5481101561460d57600f818154811061444c5761444c615132565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a082319060240160206040518083038186803b1580156144be57600080fd5b505afa1580156144d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144f69190614d25565b614513614504846001614fa9565b61109460145461109486613291565b1115600f828154811061452857614528615132565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166044820152605801604051602081830303815290604052906145fa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5080614605816150ca565b91505061442f565b5060145461462d9061462490611094846001613586565b60065490613586565b600655614638614682565b60045460405173ffffffffffffffffffffffffffffffffffffffff90911681527f6f2b3b3aaf1881d69a5d40565500f93ea73df36e7b6a29bf48b21479a9237fe990602001610e3c565b600061468c611d76565b905060005b6015548110156146e6578181815181106146ad576146ad615132565b6020026020010151601582815481106146c8576146c8615132565b600091825260209091200155806146de816150ca565b915050614691565b506146ef61434f565b60075550565b60008184841115614733576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5060006147408486615039565b95945050505050565b60008183614784576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5060006147408486614fc1565b801561479f5761479f613561565b73ffffffffffffffffffffffffffffffffffffffff8216156131a45760008060006147c985612554565b9250925092506147d885614a5f565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d6020526040902082905582811061485c57600061481382856135ff565b601c549091506148239082613586565b601c556148308482613586565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e60205260409020555061214b565b600061486884836135ff565b601c5490915061487890826135ff565b601c5561488584826135ff565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916149529190614dfa565b6000604051808303816000865af19150503d806000811461498f576040519150601f19603f3d011682016040523d82523d6000602084013e614994565b606091505b50915091508180156149be5750805115806149be5750808060200190518101906149be9190614cef565b614347576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b6000818310614a585781611a36565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811615614b5f576000614a8682610a8e565b905060005b8151811015614af457818181518110614aa657614aa6615132565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580614aec816150ca565b915050614a8b565b5060005b815181101561254f5760158181548110614b1457614b14615132565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580614b57816150ca565b915050614af8565b50565b803573ffffffffffffffffffffffffffffffffffffffff81168114614b8657600080fd5b919050565b600060208284031215614b9d57600080fd5b611a3682614b62565b60008060408385031215614bb957600080fd5b614bc283614b62565b9150614bd060208401614b62565b90509250929050565b60008060008060808587031215614bef57600080fd5b614bf885614b62565b9350614c0660208601614b62565b9250614c1460408601614b62565b91506060850135614c2481615190565b939692955090935050565b60008060408385031215614c4257600080fd5b614c4b83614b62565b946020939093013593505050565b600080600060608486031215614c6e57600080fd5b614c7784614b62565b9250602084013591506040840135614c8e81615190565b809150509250925092565b60008060008060808587031215614caf57600080fd5b614cb885614b62565b966020860135965060408601359560600135945092505050565b600060208284031215614ce457600080fd5b8135611a3681615190565b600060208284031215614d0157600080fd5b8151611a3681615190565b600060208284031215614d1e57600080fd5b5035919050565b600060208284031215614d3757600080fd5b5051919050565b60008060408385031215614d5157600080fd5b50508035926020909101359150565b60008060408385031215614d7357600080fd5b505080516020909101519092909150565b600080600060608486031215614d9957600080fd5b505081359360208301359350604090920135919050565b60008151808452614dc8816020860160208601615050565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251614e0c818460208701615050565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015614e6457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614e32565b50909695505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614ee3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614ed1858351614db0565b94509285019290850190600101614e97565b5092979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015614f515781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614f0d565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614e6457835183529284019291840191600101614f7a565b602081526000611a366020830184614db0565b60008219821115614fbc57614fbc615103565b500190565b600082614ff7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561503457615034615103565b500290565b60008282101561504b5761504b615103565b500390565b60005b8381101561506b578181015183820152602001615053565b8381111561134c5750506000910152565b600181811c9082168061509057607f821691505b60208210811415610c53577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156150fc576150fc615103565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8015158114614b5f57600080fdfea264697066735822122092cb052ff4655d13562470bc5cd9a0eb275980daac617e040bce4a52ce18670164736f6c63430008060033000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd0000000000000000000000005af15da84a4a6edf2d9fa6720de921e1026e37b7000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000346585300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003534454000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d000000000000000000000000073968b9a57c6e53d41345fd57a6e6ae27d6cdb2f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2000000000000000000000000f930ebbd05ef8b25b1797b9b2109ddc9b0d43063000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000a86cc92e3da00000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104715760003560e01c806379ba509711610250578063cdc82e8011610150578063ebe2b12b116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d114610a61578063fce6fd1314610a74578063fff6cae914610a8657600080fd5b8063f2a8d34914610a45578063f2caeb1e14610a4e57600080fd5b8063ebe2b12b146109fd578063ee89e02f14610a06578063f12f144714610a29578063f288baf614610a3c57600080fd5b8063de1a65511161011f578063e1ba95d211610104578063e1ba95d2146109cf578063e9f2838e146109d7578063eb3c209e146109ea57600080fd5b8063de1a6551146109b4578063e01f62bf146109c757600080fd5b8063cdc82e801461095a578063d239f00314610963578063d42fc9b41461096b578063d9f96e8d1461097e57600080fd5b80639637927f116101e3578063af00f4e2116101b2578063bbb781cc11610197578063bbb781cc14610929578063c8f33c911461093e578063cc1a378f1461094757600080fd5b8063af00f4e21461090d578063b94c4dcb1461092057600080fd5b80639637927f146108b95780639b8c15a8146108c65780639c5303eb146108f2578063a2217bc51461090557600080fd5b80638980f11f1161021f5780638980f11f146108455780638bad86a7146108585780638da5cb5b14610886578063941d9f65146108a657600080fd5b806379ba50971461080f5780637a2ae103146108175780637b31c19a1461082a5780637bb7bed11461083257600080fd5b8063386a9525116103765780635bfd9258116102ee57806369339245116102bd5780636e27cef9116102a25780636e27cef9146107de57806370641a36146107e757806372f702f3146107ef57600080fd5b806369339245146107ab5780636ce46bc3146107cb57600080fd5b80635bfd92581461077357806364f2c0601461077b57806366b237d01461078357806366e9e9b31461079657600080fd5b806349fb388a1161034557806351e3fc171161032a57806351e3fc17146106db57806352732bc8146106ee57806353a47bb71461075357600080fd5b806349fb388a146106a85780634fd2b536146106c857600080fd5b8063386a9525146106595780633b8105b3146106625780633d18b9121461066a57806341a16f3f1461067257600080fd5b80631e090f011161040957806328ef934e116103d857806331ca208c116103bd57806331ca208c146105ec578063323331ca1461060f57806336f89af21461062357600080fd5b806328ef934e146105c65780632c0c2a0a146105d957600080fd5b80631e090f01146105505780631e368980146105705780631f5848de14610590578063231b68dc146105a357600080fd5b806317b18c891161044557806317b18c89146104ea5780631b3e870a146104fd5780631c1f78eb146105105780631c56f33e1461051857600080fd5b80628cc262146104765780630d7bac4f1461049f57806312edb24c146104c05780631627540c146104d5575b600080fd5b610489610484366004614b8b565b610a8e565b6040516104969190614f5e565b60405180910390f35b6104b26104ad366004614d0c565b610c59565b604051908152602001610496565b6104c8610cb2565b6040516104969190614e16565b6104e86104e3366004614b8b565b610d21565b005b6104e86104f8366004614d3e565b610e47565b6104e861050b366004614b8b565b610ecd565b61048961102e565b61052b610526366004614d0c565b6110cd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610496565b61056361055e366004614b8b565b611104565b6040516104969190614ef0565b61058361057e366004614d0c565b6111b8565b6040516104969190614f96565b6104e861059e366004614c59565b611264565b6105b66105b1366004614ba6565b611352565b6040519015158152602001610496565b6104e86105d4366004614c99565b6113c1565b6104b26105e7366004614b8b565b6114f8565b6105b66105fa366004614b8b565b60236020526000908152604090205460ff1681565b6024546105b6906301000000900460ff1681565b6104b2610631366004614b8b565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b6104b260145481565b6104e8611603565b6104896116c1565b61052b610680366004614b8b565b600e6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60055461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26106d6366004614b8b565b6117bb565b6104e86106e9366004614d0c565b6117d8565b6104e86106fc366004614b8b565b3360009081526020808052604080832073ffffffffffffffffffffffffffffffffffffffff9490941683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60015461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104b26118ce565b601c546104b2565b6104b2610791366004614d0c565b611a3d565b61079e611a5e565b6040516104969190614e70565b6104b26107b9366004614b8b565b60136020526000908152604090205481565b6104e86107d9366004614d84565b611b37565b6104b2600a5481565b610489611d76565b60045461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104e8611ec7565b6104e8610825366004614bd9565b612012565b6104e8612152565b61052b610840366004614d0c565b61220f565b6104e8610853366004614c2f565b61221f565b61086b610866366004614b8b565b612554565b60408051938452602084019290925290820152606001610496565b60005461052b9073ffffffffffffffffffffffffffffffffffffffff1681565b6104e86108b4366004614b8b565b612815565b6024546105b69060ff1681565b6105b66108d4366004614ba6565b60208080526000928352604080842090915290825290205460ff1681565b6104e8610900366004614b8b565b6128ea565b6104e86129ba565b6104e861091b366004614d3e565b612a75565b6104b260095481565b6024546105b690640100000000900460ff1681565b6104b260075481565b6104e8610955366004614d0c565b612c40565b6104b260085481565b6104e8612dd9565b6104b2610979366004614b8b565b612e95565b6104b261098c366004614b8b565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b6104e86109c2366004614ba6565b612ed5565b601b546104b2565b6104e8612fbc565b6024546105b69062010000900460ff1681565b6104e86109f8366004614c2f565b61306f565b6104b260065481565b6105b6610a14366004614b8b565b601f6020526000908152604090205460ff1681565b6104e8610a37366004614b8b565b6131a8565b6104b2600c5481565b6104b2600b5481565b6104b2610a5c366004614d0c565b613291565b6104e8610a6f366004614cd2565b613371565b6024546105b690610100900460ff1681565b6104e8613561565b60606000610a9a611d76565b600f5490915067ffffffffffffffff811115610ab857610ab8615161565b604051908082528060200260200182016040528015610ae1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040902054909250610b535760005b600f54811015610b4d576000838281518110610b3057610b30615132565b602090810291909101015280610b45816150ca565b915050610b12565b50610c53565b60005b600f54811015610c515773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351610c229291610c1c91670de0b6b3a764000091610c1691610bea9190899089908110610bd457610bd4615132565b60200260200101516135ff90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602052604090205490613641565b906136f6565b90613586565b838281518110610c3457610c34615132565b602090810291909101015280610c49816150ca565b915050610b56565b505b50919050565b600080610c9b610c8c600954610c16610c85670de0b6b3a76400006008546135ff90919063ffffffff16565b8790613641565b670de0b6b3a764000090613586565b9050600854811115610cac57506008545b92915050565b6060600f805480602002602001604051908101604052809291908181526020018280548015610d1757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610cec575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b600280541415610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b60028055610ec43380848442613738565b50506001600255565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604090205460ff161515600114610fe2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60115460609067ffffffffffffffff81111561104c5761104c615161565b604051908082528060200260200182016040528015611075578160200160208202803683370190505b50905060005b6011548110156110c95761109a60145461109483613291565b90613641565b8282815181106110ac576110ac615132565b6020908102919091010152806110c1816150ca565b91505061107b565b5090565b601081815481106110dd57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602260209081526040808320805482518185028101850190935280835260609492939192909184015b828210156111ad57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190611149565b505050509050919050565b601281815481106111c857600080fd5b9060005260206000200160009150905080546111e39061507c565b80601f016020809104026020016040519081016040528092919081815260200182805461120f9061507c565b801561125c5780601f106112315761010080835404028352916020019161125c565b820191906000526020600020905b81548152906001019060200180831161123f57829003601f168201915b505050505081565b600054839073ffffffffffffffffffffffffffffffffffffffff1633148061129157506112913382611352565b6112f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205460118054859290811061133257611332615132565b600091825260209091200155811561134c5761134c613561565b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8481169116141561137e57506001610cac565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600e6020526040902054811690841614156113b857506001610cac565b50600092915050565b60245460ff610100909104161515600114611438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020808052604080832033845290915290205460ff1680156114855750336000908152601f602052604090205460ff165b6114eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610dc4565b61134c8433858585613738565b600080611504836117bb565b905080156113b8576003546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526000926115c5928592610c1692670de0b6b3a7640000929116906370a082319060240160206040518083038186803b15801561158d57600080fd5b505afa1580156115a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110949190614d25565b905060006115ea670de0b6b3a7640000610c16600c548561364190919063ffffffff16565b9050600c548111156115fb5750600c545b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff81166401000000009182900460ff1615909102179055565b606060028054141561172f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b600280556024546301000000900460ff16156117a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610dc4565b6117b13333613c30565b9050600160025590565b6000610cac670de0b6b3a7640000610c16600b5461109486612e95565b600280541415611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610dc4565b6002805560245462010000900460ff16156118bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610dc4565b6118c6333383613f07565b506001600255565b6000806000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561193b57600080fd5b505afa15801561194f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119739190614d25565b90506002611a2c600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1a9190614d25565b610c1684670de0b6b3a7640000613641565b611a369190614fc1565b9392505050565b60118181548110611a4d57600080fd5b600091825260209091200154905081565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015611b2e578382906000526020600020018054611aa19061507c565b80601f0160208091040260200160405190810160405280929190818152602001828054611acd9061507c565b8015611b1a5780601f10611aef57610100808354040283529160200191611b1a565b820191906000526020600020905b815481529060010190602001808311611afd57829003601f168201915b505050505081526020019060010190611a82565b50505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314611bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b670de0b6b3a7640000831015611c4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4d756c74206d757374206265203e3d204d554c5449504c4945525f505245434960448201527f53494f4e000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b60008111611cb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f766546585320706374206d6178206d757374206265203e3d20300000000000006044820152606401610dc4565b6008839055600c829055600b8190556040518281527fc9d56ccdd6b954d8d74700db074cc667054f8e33c1b8d23e97021d4c588a87619060200160405180910390a17fa1676084a9eea08c6f205b60799323b364a1bd8e10aba89f0fbd94cfbf68b5dd600854604051611d2e91815260200190565b60405180910390a17f58c7ececaeb4704a0039e0d22c1b618367f7a7b9a4e191ab9baed34898f63f2e600b54604051611d6991815260200190565b60405180910390a1505050565b6060601b5460001480611d895750601c54155b15611de3576015805480602002602001604051908101604052809291908181526020018280548015610d1757602002820191906000526020600020905b815481526020019060010190808311611dc6575050505050905090565b600f5467ffffffffffffffff811115611dfe57611dfe615161565b604051908082528060200260200182016040528015611e27578160200160208202803683370190505b50905060005b6015548110156110c957611e98611e6c601c54610c16670de0b6b3a7640000611094611e5887613291565b611094600754611e6661434f565b906135ff565b60158381548110611e7f57611e7f615132565b906000526020600020015461358690919063ffffffff16565b828281518110611eaa57611eaa615132565b602090810291909101015280611ebf816150ca565b915050611e2d565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610dc4565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061203f575061203f3382611352565b6120a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601360205260409020546010805485929081106120e0576120e0615132565b600091825260209091200180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560058054909116918616919091179055811561214b5761214b613561565b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146121d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff811663010000009182900460ff1615909102179055565b600f81815481106110dd57600080fd5b600054829073ffffffffffffffffffffffffffffffffffffffff1633148061224c575061224c3382611352565b6122b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b6000805b600f5481101561232d578473ffffffffffffffffffffffffffffffffffffffff16600f82815481106122ea576122ea615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561231b576001915061232d565b80612325816150ca565b9150506122b6565b50808015612361575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600e60205260409020541633145b1561246a576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff85169063a9059cbb906044015b602060405180830381600087803b1580156123d557600080fd5b505af11580156123e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240d9190614cef565b506040805133815273ffffffffffffffffffffffffffffffffffffffff861660208201529081018490527ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b6489060600160405180910390a150505050565b8015801561248f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b156124ed576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff85169063a9059cbb906044016123bb565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610dc4565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080612585846114f8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d6020526040812054919350901580156125df575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b156125eb575081612626565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d602052604090205461262390600290610c16908690613586565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff861660009081526022602052604090205481101561280c5773ffffffffffffffffffffffffffffffffffffffff8616600090815260226020526040812080548390811061269157612691615132565b90600052602060002090600502016040518060a0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600081608001519050428260600151116127c057606082015173ffffffffffffffffffffffffffffffffffffffff891660009081526018602052604090205410156127b55773ffffffffffffffffffffffffffffffffffffffff88166000908152601860205260408120546060840151612757916135ff565b905060006127728460600151426135ff90919063ffffffff16565b9050600061279561278b670de0b6b3a764000084613641565b610c1c8686613641565b90506127ab6127a48484613586565b82906136f6565b93505050506127c0565b50670de0b6b3a76400005b604082015160006127e7670de0b6b3a7640000610c166127e0868a613586565b8590613641565b90506127f38782613586565b9650505050508080612804906150ca565b91505061262d565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff16600090815260236020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461296b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314612af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b6001821015612b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d756c206d61782074696d65206d757374206265203e3d2031000000000000006044820152606401610dc4565b6001811015612bcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d756c206d696e2074696d65206d757374206265203e3d2031000000000000006044820152606401610dc4565b6009829055600a8190556040518281527f0e3e3fae480c6f92291358a02bc83f04ee1971d5488596bffda7929d57ab470f9060200160405180910390a16040518181527f0534d208d75dfdbfacc1204745dd9b3c4c37e8cfc05eb5e8e3ae538aedb0a9fa9060200160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b62015180811015612d2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f52657761726473206475726174696f6e20746f6f2073686f72740000000000006044820152606401610dc4565b6006541580612d3e575060065442115b612da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52657761726420706572696f6420696e636f6d706c65746500000000000000006044820152606401610dc4565b60148190556040518181527ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d390602001610e3c565b60005473ffffffffffffffffffffffffffffffffffffffff163314612e5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff8116620100009182900460ff1615909102179055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054610cac90670de0b6b3a764000090610c16906110946118ce565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612f025750612f023382611352565b612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610dc4565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600e6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461303d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610dc4565b602480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60245460ff6101009091041615156001146130e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020808052604080832033845290915290205460ff1680156131335750336000908152601f602052604090205460ff165b613199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d69672e20696e76616c6964206f7220756e617070726f7665640000000000006044820152606401610dc4565b6131a4823383613f07565b5050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604090205460ff16613237576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206d69677261746f72206164647265737300000000000000006044820152606401610dc4565b3360009081526020808052604080832073ffffffffffffffffffffffffffffffffffffffff9490941683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600080601083815481106132a7576132a7615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561334b57613344670de0b6b3a7640000610c16601986815481106132f3576132f3615132565b90600052602060002001548473ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b815260040160206040518083038186803b15801561158d57600080fd5b9150610c53565b6011838154811061335e5761335e615132565b9060005260206000200154915050919050565b60005b6010548110156131a45760006010828154811061339357613393615132565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561354e5782806133e55750601a82815481106133d7576133d7615132565b906000526020600020015442115b1561354e576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee190604401602060405180830381600087803b15801561345757600080fd5b505af115801561346b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348f9190614d25565b601983815481106134a2576134a2615132565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f657600080fd5b505afa15801561350a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352e9190614d25565b601a838154811061354157613541615132565b6000918252602090912001555b5080613559816150ca565b915050613374565b61356b6000613371565b600654421061357e5761357c614362565b565b61357c614682565b6000806135938385614fa9565b905083811015611a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610dc4565b6000611a3683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506146f5565b60008261365057506000610cac565b600061365c8385614ffc565b9050826136698583614fc1565b14611a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b6000611a3683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614749565b8460016137458282614791565b602454640100000000900460ff16156137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610dc4565b60008511613824576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d757374207374616b65206d6f7265207468616e207a65726f000000000000006044820152606401610dc4565b73ffffffffffffffffffffffffffffffffffffffff871660009081526023602052604090205460ff16156138b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4164647265737320686173206265656e20677265796c697374656400000000006044820152606401610dc4565b600a54841015613920576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610dc4565b60095484111561398c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610dc4565b600061399785610c59565b73ffffffffffffffffffffffffffffffffffffffff89166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608e901b169281019290925260348201889052605482018a9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8d1660009081526022835283902060a0850184528185529184018990529183018a90529092509060608101613a8a888a613586565b815260209081018590528254600181810185556000948552938290208351600590920201908155908201519281019290925560408101516002830155606081015160038301556080015160049182015554613afd9073ffffffffffffffffffffffffffffffffffffffff1689308a6148b3565b601b54613b0a9088613586565b601b5573ffffffffffffffffffffffffffffffffffffffff89166000908152601d6020526040902054613b3d9088613586565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812091909155613b71908a90614791565b73ffffffffffffffffffffffffffffffffffffffff8916600090815260186020526040902054613bc45773ffffffffffffffffffffffffffffffffffffffff891660009081526018602052604090204290555b604080518881526020810188905290810182905273ffffffffffffffffffffffffffffffffffffffff89811660608301528a16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a2505050505050505050565b6060826001613c3f8282614791565b600f5467ffffffffffffffff811115613c5a57613c5a615161565b604051908082528060200260200182016040528015613c83578160200160208202803683370190505b50925060005b600f54811015613ed75773ffffffffffffffffffffffffffffffffffffffff861660009081526017602090815260408083208484529091529020548451859083908110613cd857613cd8615132565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff8716600090815260178252604080822084835290925290812055600f805482908110613d2a57613d2a615132565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86868481518110613d8357613d83615132565b60200260200101516040518363ffffffff1660e01b8152600401613dc992919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381600087803b158015613de357600080fd5b505af1158015613df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e1b9190614cef565b508573ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613e6657613e66615132565b6020026020010151600f8481548110613e8157613e81615132565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff9182169284019290925289169082015260600160405180910390a280613ecf816150ca565b915050613c89565b50505073ffffffffffffffffffffffffffffffffffffffff90921660009081526018602052604090204290555090565b613f118383613c30565b50613f476040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600060408201819052805b73ffffffffffffffffffffffffffffffffffffffff861660009081526022602052604090205481101561406d5773ffffffffffffffffffffffffffffffffffffffff86166000908152602260205260409020805482908110613fb657613fb6615132565b90600052602060002090600502016000015484141561405b5773ffffffffffffffffffffffffffffffffffffffff8616600090815260226020526040902080548290811061400657614006615132565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050925080915061406d565b80614065816150ca565b915050613f52565b50815183146140d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610dc4565b8160600151421015806140f2575060245460ff1615156001145b806141115750336000908152601f602052604090205460ff1615156001145b614177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610dc4565b6040820151801561434757601b5461418f90826135ff565b601b5573ffffffffffffffffffffffffffffffffffffffff86166000908152601d60205260409020546141c290826135ff565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601d6020908152604080832093909355602290522080548390811061420557614205615132565b60009182526020822060059091020181815560018101829055600281018290556003810182905560040181905561423d908790614791565b600480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116938201939093526024810184905291169063a9059cbb90604401602060405180830381600087803b1580156142b357600080fd5b505af11580156142c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142eb9190614cef565b50604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff878116828401529151918816917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b505050505050565b600061435d42600654614a49565b905090565b6005546040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169063092193ab906024016040805180830381600087803b1580156143cc57600080fd5b505af11580156143e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144049190614d60565b50506000601454614420600654426135ff90919063ffffffff16565b61442a9190614fc1565b905060005b600f5481101561460d57600f818154811061444c5761444c615132565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a082319060240160206040518083038186803b1580156144be57600080fd5b505afa1580156144d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144f69190614d25565b614513614504846001614fa9565b61109460145461109486613291565b1115600f828154811061452857614528615132565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166044820152605801604051602081830303815290604052906145fa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5080614605816150ca565b91505061442f565b5060145461462d9061462490611094846001613586565b60065490613586565b600655614638614682565b60045460405173ffffffffffffffffffffffffffffffffffffffff90911681527f6f2b3b3aaf1881d69a5d40565500f93ea73df36e7b6a29bf48b21479a9237fe990602001610e3c565b600061468c611d76565b905060005b6015548110156146e6578181815181106146ad576146ad615132565b6020026020010151601582815481106146c8576146c8615132565b600091825260209091200155806146de816150ca565b915050614691565b506146ef61434f565b60075550565b60008184841115614733576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5060006147408486615039565b95945050505050565b60008183614784576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc49190614f96565b5060006147408486614fc1565b801561479f5761479f613561565b73ffffffffffffffffffffffffffffffffffffffff8216156131a45760008060006147c985612554565b9250925092506147d885614a5f565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600d6020526040902082905582811061485c57600061481382856135ff565b601c549091506148239082613586565b601c556148308482613586565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e60205260409020555061214b565b600061486884836135ff565b601c5490915061487890826135ff565b601c5561488584826135ff565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916149529190614dfa565b6000604051808303816000865af19150503d806000811461498f576040519150601f19603f3d011682016040523d82523d6000602084013e614994565b606091505b50915091508180156149be5750805115806149be5750808060200190518101906149be9190614cef565b614347576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610dc4565b6000818310614a585781611a36565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811615614b5f576000614a8682610a8e565b905060005b8151811015614af457818181518110614aa657614aa6615132565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580614aec816150ca565b915050614a8b565b5060005b815181101561254f5760158181548110614b1457614b14615132565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580614b57816150ca565b915050614af8565b50565b803573ffffffffffffffffffffffffffffffffffffffff81168114614b8657600080fd5b919050565b600060208284031215614b9d57600080fd5b611a3682614b62565b60008060408385031215614bb957600080fd5b614bc283614b62565b9150614bd060208401614b62565b90509250929050565b60008060008060808587031215614bef57600080fd5b614bf885614b62565b9350614c0660208601614b62565b9250614c1460408601614b62565b91506060850135614c2481615190565b939692955090935050565b60008060408385031215614c4257600080fd5b614c4b83614b62565b946020939093013593505050565b600080600060608486031215614c6e57600080fd5b614c7784614b62565b9250602084013591506040840135614c8e81615190565b809150509250925092565b60008060008060808587031215614caf57600080fd5b614cb885614b62565b966020860135965060408601359560600135945092505050565b600060208284031215614ce457600080fd5b8135611a3681615190565b600060208284031215614d0157600080fd5b8151611a3681615190565b600060208284031215614d1e57600080fd5b5035919050565b600060208284031215614d3757600080fd5b5051919050565b60008060408385031215614d5157600080fd5b50508035926020909101359150565b60008060408385031215614d7357600080fd5b505080516020909101519092909150565b600080600060608486031215614d9957600080fd5b505081359360208301359350604090920135919050565b60008151808452614dc8816020860160208601615050565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251614e0c818460208701615050565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015614e6457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614e32565b50909695505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614ee3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614ed1858351614db0565b94509285019290850190600101614e97565b5092979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015614f515781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614f0d565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614e6457835183529284019291840191600101614f7a565b602081526000611a366020830184614db0565b60008219821115614fbc57614fbc615103565b500190565b600082614ff7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561503457615034615103565b500290565b60008282101561504b5761504b615103565b500390565b60005b8381101561506b578181015183820152602001615053565b8381111561134c5750506000910152565b600181811c9082168061509057607f821691505b60208210811415610c53577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156150fc576150fc615103565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8015158114614b5f57600080fdfea264697066735822122092cb052ff4655d13562470bc5cd9a0eb275980daac617e040bce4a52ce18670164736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd0000000000000000000000005af15da84a4a6edf2d9fa6720de921e1026e37b7000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000346585300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003534454000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d000000000000000000000000073968b9a57c6e53d41345fd57a6e6ae27d6cdb2f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2000000000000000000000000f930ebbd05ef8b25b1797b9b2109ddc9b0d43063000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000a86cc92e3da00000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0xfF5B4BCbf765FE363269114e1c765229a29eDeFD
Arg [1] : _stakingToken (address): 0x5af15DA84A4a6EDf2d9FA6720De921E1026E37b7
Arg [2] : _rewards_distributor_address (address): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34
Arg [3] : _rewardSymbols (string[]): FXS,SDT
Arg [4] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0x73968b9a57c6E53d41345FD57a6E6ae27d6CDB2F
Arg [5] : _rewardManagers (address[]): 0x234D953a9404Bf9DbC3b526271d440cD2870bCd2,0xF930EBBd05eF8b25B1797b9b2109DDC9B0d43063
Arg [6] : _rewardRates (uint256[]): 11574074074074,11574074074074
Arg [7] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000
-----Encoded View---------------
27 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff5b4bcbf765fe363269114e1c765229a29edefd
Arg [1] : 0000000000000000000000005af15da84a4a6edf2d9fa6720de921e1026e37b7
Arg [2] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000240
Arg [6] : 00000000000000000000000000000000000000000000000000000000000002a0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000300
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [12] : 4658530000000000000000000000000000000000000000000000000000000000
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [14] : 5344540000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [16] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [17] : 00000000000000000000000073968b9a57c6e53d41345fd57a6e6ae27d6cdb2f
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [19] : 000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2
Arg [20] : 000000000000000000000000f930ebbd05ef8b25b1797b9b2109ddc9b0d43063
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [22] : 00000000000000000000000000000000000000000000000000000a86cc92e3da
Arg [23] : 00000000000000000000000000000000000000000000000000000a86cc92e3da
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
119310:588:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99371:714;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97311:450;;;;;;:::i;:::-;;:::i;:::-;;;21916:25:1;;;21904:2;21889:18;97311:450:0;21871:76:1;97134:109:0;;;:::i;:::-;;;;;;;:::i;81078:141::-;;;;;;:::i;:::-;;:::i;:::-;;103686:163;;;;;;:::i;:::-;;:::i;113176:260::-;;;;;;:::i;:::-;;:::i;100149:342::-;;;:::i;85521:33::-;;;;;;:::i;:::-;;:::i;:::-;;;6035:42:1;6023:55;;;6005:74;;5993:2;5978:18;85521:33:0;5960:125:1;96798:133:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;85602:29::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;117280:286::-;;;;;;:::i;:::-;;:::i;100565:298::-;;;;;;:::i;:::-;;:::i;:::-;;;10498:14:1;;10491:22;10473:41;;10461:2;10446:18;100565:298:0;10428:92:1;112267:357:0;;;;;;:::i;:::-;;:::i;93127:928::-;;;;;;:::i;:::-;;:::i;86992:40::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;87320:35;;;;;;;;;;;;91179:127;;;;;;:::i;:::-;91272:26;;91245:7;91272:26;;;:17;:26;;;;;;;91179:127;85757:39;;;;;;116756:95;;;:::i;108140:210::-;;;:::i;85399:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;84394:58;;;;;;;;;92932:187;;;;;;:::i;:::-;;:::i;105932:194::-;;;;;;:::i;:::-;;:::i;101256:183::-;;;;;;:::i;:::-;101402:10;101377:36;;;;:24;:36;;;;;;;;:54;;;;;;;;;;101370:61;;;;;;101256:183;80846:29;;;;;;;;;91314:1445;;;:::i;91013:111::-;91094:22;;91013:111;;85561:34;;;;;;:::i;:::-;;:::i;96989:107::-;;;:::i;:::-;;;;;;;:::i;85638:55::-;;;;;;:::i;:::-;;;;;;;;;;;;;;115172:795;;;;;;:::i;:::-;;:::i;84959:36::-;;;;;;98465:690;;;:::i;84223:34::-;;;;;;;;;81227:271;;;:::i;117643:448::-;;;;;;:::i;:::-;;:::i;117078:125::-;;;:::i;85485:29::-;;;;;;:::i;:::-;;:::i;113565:1197::-;;;;;;:::i;:::-;;:::i;94117:2623::-;;;;;;:::i;:::-;;:::i;:::-;;;;23375:25:1;;;23431:2;23416:18;;23409:34;;;;23459:18;;;23452:34;23363:2;23348:18;94117:2623:0;23330:162:1;80819:20:0;;;;;;;;;116519:125;;;;;;:::i;:::-;;:::i;87073:26::-;;;;;;;;;86732:76;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;113007:127;;;;;;:::i;:::-;;:::i;116859:96::-;;;:::i;115975:536::-;;;;;;:::i;:::-;;:::i;84880:61::-;;;;;;87381:25;;;;;;;;;;;;84726:29;;;;;;114770:394;;;;;;:::i;:::-;;:::i;84806:50::-;;;;;;116963:107;;;:::i;92767:157::-;;;;;;:::i;:::-;;:::i;90731:128::-;;;;;;:::i;:::-;90825:26;;90798:7;90825:26;;;:17;:26;;;;;;;90731:128;118166:207;;;;;;:::i;:::-;;:::i;90565:113::-;90647:23;;90565:113;;116652:96;;;:::i;87265:29::-;;;;;;;;;;;;112660:298;;;;;;:::i;:::-;;:::i;84692:27::-;;;;;;86621:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;100962:226;;;;;;:::i;:::-;;:::i;85179:51::-;;;;;;85048:59;;;;;;97954:458;;;;;;:::i;:::-;;:::i;111038:761::-;;;;;;:::i;:::-;;:::i;87152:24::-;;;;;;;;;;;;111807:277;;;:::i;99371:714::-;99425:27;99465;99495:17;:15;:17::i;:::-;99550:12;:19;99465:47;;-1:-1:-1;99536:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;99536:34:0;-1:-1:-1;99587:26:0;;;;;;;:17;:26;;;;;;99523:47;;-1:-1:-1;99583:495:0;;99639:9;99634:102;99658:12;:19;99654:23;;99634:102;;;99719:1;99703:10;99714:1;99703:13;;;;;;;;:::i;:::-;;;;;;;;;;:17;99679:3;;;;:::i;:::-;;;;99634:102;;;;99583:495;;;99782:9;99777:290;99801:12;:19;99797:23;;99777:290;;;100031:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;99935:32;;;:23;:32;;;;;:35;;;;;;;;;99917:13;;99862:189;;100031:19;99862:142;;99999:4;;99862:110;;99917:54;;99935:35;99917:10;;100048:1;;99917:13;;;;;;:::i;:::-;;;;;;;:17;;:54;;;;:::i;:::-;99863:26;;;;;;;:17;:26;;;;;;;99862:54;:110::i;:::-;:136;;:142::i;:::-;:168;;:189::i;:::-;99846:10;99857:1;99846:13;;;;;;;;:::i;:::-;;;;;;;;;;:205;99822:3;;;;:::i;:::-;;;;99777:290;;;;99583:495;99454:631;99371:714;;;:::o;97311:450::-;97370:7;97390:23;97429:200;97481:133;97585:28;;97481:77;97512:45;84657:4;97512:19;;:23;;:45;;;;:::i;:::-;97481:4;;:30;:77::i;:133::-;84657:4;;97429:33;:200::i;:::-;97390:239;;97662:19;;97644:15;:37;97640:80;;;-1:-1:-1;97701:19:0;;97640:80;97738:15;97311:450;-1:-1:-1;;97311:450:0:o;97134:109::-;97187:16;97223:12;97216:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97134:109;:::o;81078:141::-;81558:5;;;;81544:10;:19;81536:79;;;;;;;16515:2:1;81536:79:0;;;16497:21:1;16554:2;16534:18;;;16527:30;16593:34;16573:18;;;16566:62;16664:17;16644:18;;;16637:45;16699:19;;81536:79:0;;;;;;;;;81150:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;81189:22:::1;::::0;6005:74:1;;;81189:22:0::1;::::0;5993:2:1;5978:18;81189:22:0::1;;;;;;;;81078:141:::0;:::o;103686:163::-;79753:1;80359:7;;:19;;80351:63;;;;;;;21261:2:1;80351:63:0;;;21243:21:1;21300:2;21280:18;;;21273:30;21339:33;21319:18;;;21312:61;21390:18;;80351:63:0;21233:181:1;80351:63:0;79753:1;80492:18;;103771:70:::1;103784:10;::::0;103808:9;103819:4;103825:15:::1;103771:12;:70::i;:::-;-1:-1:-1::0;;79709:1:0;80671:7;:22;103686:163::o;113176:260::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;113266:33:::1;::::0;::::1;;::::0;;;:15:::1;:33;::::0;;;;;::::1;;:41;;:33:::0;:41:::1;113258:73;;;::::0;::::1;::::0;;18044:2:1;113258:73:0::1;::::0;::::1;18026:21:1::0;18083:2;18063:18;;;18056:30;18122:21;18102:18;;;18095:49;18161:18;;113258:73:0::1;18016:169:1::0;113258:73:0::1;113395:33;;;::::0;;;:15:::1;:33;::::0;;;;113388:40;;;::::1;::::0;;113176:260::o;100149:342::-;100299:17;:24;100204:41;;100285:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;100285:39:0;;100258:66;;100342:9;100337:147;100361:17;:24;100357:28;;100337:147;;;100437:35;100456:15;;100437:14;100449:1;100437:11;:14::i;:::-;:18;;:35::i;:::-;100407:24;100432:1;100407:27;;;;;;;;:::i;:::-;;;;;;;;;;:65;100387:3;;;;:::i;:::-;;;;100337:147;;;;100149:342;:::o;85521:33::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85521:33:0;:::o;96798:133::-;96902:21;;;;;;;:12;:21;;;;;;;;96895:28;;;;;;;;;;;;;;;;;96862:20;;96895:28;;96902:21;;96895:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96798:133;;;:::o;85602:29::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;117280:286::-;87949:5;;117387:20;;87949:5;;87935:10;:19;;:74;;;87958:51;87976:10;87988:20;87958:17;:51::i;:::-;87927:107;;;;;;;20507:2:1;87927:107:0;;;20489:21:1;20546:2;20526:18;;;20519:30;20585:22;20565:18;;;20558:50;20625:18;;87927:107:0;20479:170:1;87927:107:0;117438:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;117420:17:::1;:61:::0;;117484:8;;117438:42;117420:61;::::1;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;:72:::0;117513:46;::::1;;;117541:6;:4;:6::i;:::-;117280:286:::0;;;;:::o;100565:298::-;100661:4;100696:5;;;100681:20;;;100696:5;;100681:20;100677:136;;;-1:-1:-1;100710:4:0;100703:11;;100677:136;100752:48;:33;;;;;;;:14;:33;;;;;;;;:48;;;;100748:65;;;-1:-1:-1;100809:4:0;100802:11;;100748:65;-1:-1:-1;100849:5:0;100565:298;;;;:::o;112267:357::-;88106:12;;;;;;;;:20;;:12;:20;88098:49;;;;;;;12253:2:1;88098:49:0;;;12235:21:1;12292:2;12272:18;;;12265:30;12331:18;12311;;;12304:46;12367:18;;88098:49:0;12225:166:1;88098:49:0;112420:40:::1;::::0;::::1;;::::0;;;:24:::1;:40:::0;;;;;;;112461:10:::1;112420:52:::0;;;;;;;;::::1;;:83:::0;::::1;;;-1:-1:-1::0;112492:10:0::1;112476:27;::::0;;;:15:::1;:27;::::0;;;;;::::1;;112420:83;112412:122;;;::::0;::::1;::::0;;17689:2:1;112412:122:0::1;::::0;::::1;17671:21:1::0;17728:2;17708:18;;;17701:30;17767:28;17747:18;;;17740:56;17813:18;;112412:122:0::1;17661:176:1::0;112412:122:0::1;112545:71;112558:14;112574:10;112586:6;112594:4;112600:15;112545:12;:71::i;93127:928::-:0;93190:7;93364:34;93401:28;93421:7;93401:19;:28::i;:::-;93364:65;-1:-1:-1;93444:30:0;;93440:538;;93522:5;;:24;;;;;:5;6023:55:1;;;93522:24:0;;;6005:74:1;93491:27:0;;93521:84;;93578:26;;93521:52;;84657:4;;93522:5;;;:15;;5978:18:1;;93522:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;93521:84::-;93491:114;;93634:24;93661:75;84657:4;93662:47;93688:20;;93663:19;93662:25;;:47;;;;:::i;93661:75::-;93634:102;;93834:20;;93815:16;:39;93811:84;;;-1:-1:-1;93875:20:0;;93811:84;93919:16;93127:928;-1:-1:-1;;;;93127:928:0:o;116756:95::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;116830:13:::1;::::0;;116813:30;;::::1;116830:13:::0;;;;::::1;;;116829:14;116813:30:::0;;::::1;;::::0;;116756:95::o;108140:210::-;108192:16;79753:1;80359:7;;:19;;80351:63;;;;;;;21261:2:1;80351:63:0;;;21243:21:1;21300:2;21280:18;;;21273:30;21339:33;21319:18;;;21312:61;21390:18;;80351:63:0;21233:181:1;80351:63:0;79753:1;80492:18;;108229:23:::1;::::0;;;::::1;;;:32;108221:69;;;::::0;::::1;::::0;;18392:2:1;108221:69:0::1;::::0;::::1;18374:21:1::0;18431:2;18411:18;;;18404:30;18470:27;18450:18;;;18443:55;18515:18;;108221:69:0::1;18364:175:1::0;108221:69:0::1;108308:34;108319:10;108331;108308;:34::i;:::-;108301:41;;79709:1:::0;80671:7;:22;108140:210;:::o;92932:187::-;92999:7;93026:85;84657:4;93026:59;93056:28;;93027:23;93042:7;93027:14;:23::i;105932:194::-;79753:1;80359:7;;:19;;80351:63;;;;;;;21261:2:1;80351:63:0;;;21243:21:1;21300:2;21280:18;;;21273:30;21339:33;21319:18;;;21312:61;21390:18;;80351:63:0;21233:181:1;80351:63:0;79753:1;80492:18;;106011:17:::1;::::0;;;::::1;;;:26;106003:57;;;::::0;::::1;::::0;;14420:2:1;106003:57:0::1;::::0;::::1;14402:21:1::0;14459:2;14439:18;;;14432:30;14498:20;14478:18;;;14471:48;14536:18;;106003:57:0::1;14392:168:1::0;106003:57:0::1;106071:47;106087:10;106099;106111:6;106071:15;:47::i;:::-;-1:-1:-1::0;79709:1:0;80671:7;:22;105932:194::o;91314:1445::-;91361:7;91442:25;92473:21;92497:12;;;;;;;;;;;:20;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92473:46;;92702:1;92644:55;92672:12;;;;;;;;;;;:24;;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92644:23;:13;92662:4;92644:17;:23::i;:55::-;:59;;;;:::i;:::-;92624:79;91314:1445;-1:-1:-1;;;91314:1445:0:o;85561:34::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85561:34:0;:::o;96989:107::-;97040:15;97075:13;97068:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96989:107;:::o;115172:795::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;84657:4:::1;115336:20;:44;;115328:93;;;::::0;::::1;::::0;;13660:2:1;115328:93:0::1;::::0;::::1;13642:21:1::0;13699:2;13679:18;;;13672:30;13738:34;13718:18;;;13711:62;13809:6;13789:18;;;13782:34;13833:19;;115328:93:0::1;13632:226:1::0;115328:93:0::1;115544:1;115512:29;:33;115504:72;;;::::0;::::1;::::0;;19452:2:1;115504:72:0::1;::::0;::::1;19434:21:1::0;19491:2;19471:18;;;19464:30;19530:28;19510:18;;;19503:56;19576:18;;115504:72:0::1;19424:176:1::0;115504:72:0::1;115589:19;:42:::0;;;115642:20:::1;:44:::0;;;115697:28:::1;:60:::0;;;115775:40:::1;::::0;21916:25:1;;;115775:40:0::1;::::0;21904:2:1;21889:18;115775:40:0::1;;;;;;;115831:52;115863:19;;115831:52;;;;21916:25:1::0;;21904:2;21889:18;;21871:76;115831:52:0::1;;;;;;;;115899:60;115930:28;;115899:60;;;;21916:25:1::0;;21904:2;21889:18;;21871:76;115899:60:0::1;;;;;;;;115172:795:::0;;;:::o;98465:690::-;98513:41;98571:23;;98598:1;98571:28;:59;;;-1:-1:-1;98603:22:0;;:27;98571:59;98567:581;;;98654:21;98647:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98465:690;:::o;98567:581::-;98758:12;:19;98744:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;98744:34:0;;98717:61;;98798:9;98793:298;98817:21;:28;98813:32;;98793:298;;;98901:174;98952:104;99033:22;;98952:76;99023:4;98952:66;99003:14;99015:1;99003:11;:14::i;:::-;98952:46;98983:14;;98952:26;:24;:26::i;:::-;:30;;:46::i;:104::-;98901:21;98923:1;98901:24;;;;;;;;:::i;:::-;;;;;;;;;:28;;:174;;;;:::i;:::-;98871:24;98896:1;98871:27;;;;;;;;:::i;:::-;;;;;;;;;;:204;98847:3;;;;:::i;:::-;;;;98793:298;;81227:271;81296:14;;;;81282:10;:28;81274:94;;;;;;;11831:2:1;81274:94:0;;;11813:21:1;11870:2;11850:18;;;11843:30;11909:34;11889:18;;;11882:62;11980:23;11960:18;;;11953:51;12021:19;;81274:94:0;11803:243:1;81274:94:0;81397:5;;;81404:14;81384:35;;;81397:5;;;;6325:34:1;;81404:14:0;;;;6390:2:1;6375:18;;6368:43;81384:35:0;;6237:18:1;81384:35:0;;;;;;;81438:14;;;;81430:22;;;;;;81438:14;;;81430:22;;;;81463:27;;;81227:271::o;117643:448::-;87949:5;;117810:20;;87949:5;;87935:10;:19;;:74;;;87958:51;87976:10;87988:20;87958:17;:51::i;:::-;87927:107;;;;;;;20507:2:1;87927:107:0;;;20489:21:1;20546:2;20526:18;;;20519:30;20585:22;20565:18;;;20558:50;20625:18;;87927:107:0;20479:170:1;87927:107:0;117860:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;117843:16:::1;:60:::0;;117906:25;;117860:42;117843:60;::::1;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;:88:::0;;;;;::::1;;::::0;;::::1;;::::0;;;117942:19:::1;:83:::0;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;118038:46;::::1;;;118066:6;:4;:6::i;:::-;117643:448:::0;;;;;:::o;117078:125::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;117172:23:::1;::::0;;117145:50;;::::1;117172:23:::0;;;;::::1;;;117171:24;117145:50:::0;;::::1;;::::0;;117078:125::o;85485:29::-;;;;;;;;;;;;113565:1197;87949:5;;113651:12;;87949:5;;87935:10;:19;;:74;;;87958:51;87976:10;87988:20;87958:17;:51::i;:::-;87927:107;;;;;;;20507:2:1;87927:107:0;;;20489:21:1;20546:2;20526:18;;;20519:30;20585:22;20565:18;;;20558:50;20625:18;;87927:107:0;20479:170:1;87927:107:0;113733:18:::1;113775:9:::0;113770:192:::1;113794:12;:19:::0;113790:23;::::1;113770:192;;;113858:12;113839:31;;:12;113852:1;113839:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:31;113835:116;;;113907:4;113891:20;;113930:5;;113835:116;113815:3:::0;::::1;::::0;::::1;:::i;:::-;;;;113770:192;;;;114049:13;:59;;;;-1:-1:-1::0;114066:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;114098:10;114066:42;114049:59;114045:710;;;114124:53;::::0;;;;114153:10:::1;114124:53;::::0;::::1;6999:74:1::0;7089:18;;;7082:34;;;114124:28:0::1;::::0;::::1;::::0;::::1;::::0;6972:18:1;;114124:53:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;114197:48:0::1;::::0;;114207:10:::1;6685:34:1::0;;6634:42;6755:15;;6750:2;6735:18;;6728:43;6787:18;;;6780:34;;;114197:48:0::1;::::0;6612:2:1;6597:18;114197:48:0::1;;;;;;;114260:7;113565:1197:::0;;;:::o;114045:710::-:1;114414:13;114413:14;:39;;;;-1:-1:-1::0;114446:5:0::1;::::0;::::1;;114432:10;:19;114413:39;114409:346;;;114468:53;::::0;;;;114497:10:::1;114468:53;::::0;::::1;6999:74:1::0;7089:18;;;7082:34;;;114468:28:0::1;::::0;::::1;::::0;::::1;::::0;6972:18:1;;114468:53:0::1;6954:168:1::0;114409:346:0::1;114707:36;::::0;::::1;::::0;;14065:2:1;114707:36:0::1;::::0;::::1;14047:21:1::0;14104:2;14084:18;;;14077:30;14143:28;14123:18;;;14116:56;14189:18;;114707:36:0::1;14037:176:1::0;88045:1:0::1;113565:1197:::0;;;:::o;94117:2623::-;94411:26;;;94209:27;94411:26;;;:17;:26;;;;;;;94209:27;94598:24;94429:7;94598:15;:24::i;:::-;94683:26;;;94635:33;94683:26;;;:17;:26;;;;;;94575:47;;-1:-1:-1;94635:33:0;94683:31;:66;;;;-1:-1:-1;94718:26:0;;;;;;;:17;:26;;;;;;:31;94683:66;94679:394;;;-1:-1:-1;94903:20:0;94679:394;;;95021:31;;;;;;;:22;:31;;;;;;94993:68;;95059:1;;94994:59;;94995:20;;94994:26;:59::i;94993:68::-;94965:96;;94679:394;95208:1;95186:23;;95225:9;95220:1513;95244:21;;;;;;;:12;:21;;;;;:28;95240:32;;95220:1513;;;95325:21;;;95294:28;95325:21;;;:12;:21;;;;;:24;;95347:1;;95325:24;;;;;;:::i;:::-;;;;;;;;;;;95294:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95364:23;95390:9;:25;;;95364:51;;95505:15;95475:9;:26;;;:45;95471:974;;95708:26;;;;95677:28;;;;;;;:19;:28;;;;;;:57;95673:757;;;95820:28;;;95758:26;95820:28;;;:19;:28;;;;;;95788:26;;;;95787:62;;:32;:62::i;:::-;95758:91;;95872:25;95900:49;95922:9;:26;;;95901:15;95900:21;;:49;;;;:::i;:::-;95872:77;-1:-1:-1;96039:17:0;96059:96;96108:45;84657:4;95872:77;96108:26;:45::i;:::-;96060:41;96061:15;96082:18;96060:21;:41::i;96059:96::-;96039:116;-1:-1:-1;96196:56:0;96210:41;:18;96233:17;96210:22;:41::i;:::-;96196:9;;:13;:56::i;:::-;96178:74;;95735:537;;;95673:757;;;-1:-1:-1;84657:4:0;95673:757;96481:19;;;;96461:17;96549:87;84657:4;96549:61;96563:46;:15;96583:25;96563:19;:46::i;:::-;96549:9;;:13;:61::i;:87::-;96515:121;-1:-1:-1;96673:48:0;:19;96515:121;96673:23;:48::i;:::-;96651:70;;95279:1454;;;;95274:3;;;;;:::i;:::-;;;;95220:1513;;;;94338:2402;94117:2623;;;;;:::o;116519:125::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;116617:18:::1;;;::::0;;;:8:::1;:18;::::0;;;;;;116594:42;;::::1;116617:18;::::0;;::::1;116615:21;116594:42;::::0;;116519:125::o;113007:127::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;113086:33:::1;;;::::0;;;:15:::1;:33;::::0;;;;:40;;;::::1;113122:4;113086:40;::::0;;113007:127::o;116859:96::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;116935:12:::1;::::0;;116919:28;;::::1;116935:12;::::0;;;::::1;;;116934:13;116919:28:::0;;::::1;;::::0;;116859:96::o;115975:536::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;116161:1:::1;116128:29;:34;;116120:72;;;::::0;::::1;::::0;;11477:2:1;116120:72:0::1;::::0;::::1;11459:21:1::0;11516:2;11496:18;;;11489:30;11555:27;11535:18;;;11528:55;11600:18;;116120:72:0::1;11449:175:1::0;116120:72:0::1;116229:1;116211:14;:19;;116203:57;;;::::0;::::1;::::0;;15818:2:1;116203:57:0::1;::::0;::::1;15800:21:1::0;15857:2;15837:18;;;15830:30;15896:27;15876:18;;;15869:55;15941:18;;116203:57:0::1;15790:175:1::0;116203:57:0::1;116273:28;:60:::0;;;116344:13:::1;:30:::0;;;116392:61:::1;::::0;21916:25:1;;;116392:61:0::1;::::0;21904:2:1;21889:18;116392:61:0::1;;;;;;;116469:34;::::0;21916:25:1;;;116469:34:0::1;::::0;21904:2:1;21889:18;116469:34:0::1;;;;;;;115975:536:::0;;:::o;114770:394::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;114884:5:::1;114864:16;:25;;114856:64;;;::::0;::::1;::::0;;14767:2:1;114856:64:0::1;::::0;::::1;14749:21:1::0;14806:2;14786:18;;;14779:30;14845:28;14825:18;;;14818:56;14891:18;;114856:64:0::1;14739:176:1::0;114856:64:0::1;114953:12;::::0;:17;;:51:::1;;;114992:12;;114974:15;:30;114953:51;114931:125;;;::::0;::::1;::::0;;19099:2:1;114931:125:0::1;::::0;::::1;19081:21:1::0;19138:2;19118:18;;;19111:30;19177:26;19157:18;;;19150:54;19221:18;;114931:125:0::1;19071:174:1::0;114931:125:0::1;115067:15;:34:::0;;;115117:39:::1;::::0;21916:25:1;;;115117:39:0::1;::::0;21904:2:1;21889:18;115117:39:0::1;21871:76:1::0;116963:107:0;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;117045:17:::1;::::0;;117024:38;;::::1;117045:17:::0;;;;::::1;;;117044:18;117024:38:::0;;::::1;;::::0;;116963:107::o;92767:157::-;92879:26;;;92829:7;92879:26;;;:17;:26;;;;;;92856:60;;92911:4;;92856:50;;92857:16;:14;:16::i;118166:207::-;87949:5;;118274:20;;87949:5;;87935:10;:19;;:74;;;87958:51;87976:10;87988:20;87958:17;:51::i;:::-;87927:107;;;;;;;20507:2:1;87927:107:0;;;20489:21:1;20546:2;20526:18;;;20519:30;20585:22;20565:18;;;20558:50;20625:18;;87927:107:0;20479:170:1;87927:107:0;-1:-1:-1;118307:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;118166:207::o;116652:96::-;87814:5;;;;87800:10;:19;87792:45;;;;;;;15476:2:1;87792:45:0;;;15458:21:1;15515:2;15495:18;;;15488:30;15554:15;15534:18;;;15527:43;15587:18;;87792:45:0;15448:163:1;87792:45:0;116726:14:::1;::::0;;116708:32;;::::1;116726:14;::::0;;::::1;116725:15;116708:32;::::0;;116652:96::o;112660:298::-;88106:12;;;;;;;;:20;;:12;:20;88098:49;;;;;;;12253:2:1;88098:49:0;;;12235:21:1;12292:2;12272:18;;;12265:30;12331:18;12311;;;12304:46;12367:18;;88098:49:0;12225:166:1;88098:49:0;112774:40:::1;::::0;::::1;;::::0;;;:24:::1;:40:::0;;;;;;;112815:10:::1;112774:52:::0;;;;;;;;::::1;;:83:::0;::::1;;;-1:-1:-1::0;112846:10:0::1;112830:27;::::0;;;:15:::1;:27;::::0;;;;;::::1;;112774:83;112766:122;;;::::0;::::1;::::0;;17689:2:1;112766:122:0::1;::::0;::::1;17671:21:1::0;17728:2;17708:18;;;17701:30;17767:28;17747:18;;;17740:56;17813:18;;112766:122:0::1;17661:176:1::0;112766:122:0::1;112899:51;112915:14;112931:10;112943:6;112899:15;:51::i;:::-;112660:298:::0;;:::o;100962:226::-;101045:33;;;;;;;:15;:33;;;;;;;;101037:70;;;;;;;18746:2:1;101037:70:0;;;18728:21:1;18785:2;18765:18;;;18758:30;18824:26;18804:18;;;18797:54;18868:18;;101037:70:0;18718:174:1;101037:70:0;101143:10;101118:36;;;;:24;:36;;;;;;;;:54;;;;;;;;;;:61;;;;101175:4;101118:61;;;100962:226::o;97954:458::-;98015:16;98044:32;98079:16;98096:9;98079:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;98121:38:0;;98117:288;;98187:125;98307:4;98187:115;98263:27;98291:9;98263:38;;;;;;;;:::i;:::-;;;;;;;;;98209:24;98188:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98187:125;98176:136;;98117:288;;;98365:17;98383:9;98365:28;;;;;;;;:::i;:::-;;;;;;;;;98354:39;;98033:379;97954:458;;;:::o;111038:761::-;111155:9;111150:642;111174:16;:23;111170:27;;111150:642;;;111219:32;111254:16;111271:1;111254:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;111292:38:0;;111288:493;;111355:12;:61;;;;111390:22;111413:1;111390:25;;;;;;;;:::i;:::-;;;;;;;;;111372:15;:43;111355:61;111351:415;;;111530:106;;;;;111613:4;111530:106;;;6999:74:1;111620:15:0;7089:18:1;;;7082:34;111530:74:0;;;;;;6972:18:1;;111530:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111497:27;111525:1;111497:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;111708:24;111687:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111659:22;111682:1;111659:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;111351:415;-1:-1:-1;111199:3:0;;;;:::i;:::-;;;;111150:642;;111807:277;111890:25;111909:5;111890:18;:25::i;:::-;111951:12;;111932:15;:31;111928:149;;111980:14;:12;:14::i;:::-;111807:277::o;111928:149::-;112036:29;:27;:29::i;2243:181::-;2301:7;;2333:5;2337:1;2333;:5;:::i;:::-;2321:17;;2362:1;2357;:6;;2349:46;;;;;;;13304:2:1;2349:46:0;;;13286:21:1;13343:2;13323:18;;;13316:30;13382:29;13362:18;;;13355:57;13429:18;;2349:46:0;13276:177:1;2699:136:0;2757:7;2784:43;2788:1;2791;2784:43;;;;;;;;;;;;;;;;;:3;:43::i;3615:471::-;3673:7;3918:6;3914:47;;-1:-1:-1;3948:1:0;3941:8;;3914:47;3973:9;3985:5;3989:1;3985;:5;:::i;:::-;3973:17;-1:-1:-1;4018:1:0;4009:5;4013:1;3973:17;4009:5;:::i;:::-;:10;4001:56;;;;;;;17287:2:1;4001:56:0;;;17269:21:1;17326:2;17306:18;;;17299:30;17365:34;17345:18;;;17338:62;17436:3;17416:18;;;17409:31;17457:19;;4001:56:0;17259:223:1;4554:132:0;4612:7;4639:39;4643:1;4646;4639:39;;;;;;;;;;;;;;;;;:3;:39::i;104045:1775::-;104260:14;104276:4;88366:42;88390:7;88399:8;88366:23;:42::i;:::-;104302:13:::1;::::0;;;::::1;;;104301:14;104293:41;;;::::0;::::1;::::0;;16172:2:1;104293:41:0::1;::::0;::::1;16154:21:1::0;16211:2;16191:18;;;16184:30;16250:16;16230:18;;;16223:44;16284:18;;104293:41:0::1;16144:164:1::0;104293:41:0::1;104365:1;104353:9;:13;104345:51;;;::::0;::::1;::::0;;15122:2:1;104345:51:0::1;::::0;::::1;15104:21:1::0;15161:2;15141:18;;;15134:30;15200:27;15180:18;;;15173:55;15245:18;;104345:51:0::1;15094:175:1::0;104345:51:0::1;104415:24;::::0;::::1;;::::0;;;:8:::1;:24;::::0;;;;;::::1;;:33;104407:73;;;::::0;::::1;::::0;;16931:2:1;104407:73:0::1;::::0;::::1;16913:21:1::0;16970:2;16950:18;;;16943:30;17009:29;16989:18;;;16982:57;17056:18;;104407:73:0::1;16903:177:1::0;104407:73:0::1;104507:13;;104499:4;:21;;104491:60;;;::::0;::::1;::::0;;12949:2:1;104491:60:0::1;::::0;::::1;12931:21:1::0;12988:2;12968:18;;;12961:30;13027:28;13007:18;;;13000:56;13073:18;;104491:60:0::1;12921:176:1::0;104491:60:0::1;104578:28;;104570:4;:36;;104562:75;;;::::0;::::1;::::0;;20151:2:1;104562:75:0::1;::::0;::::1;20133:21:1::0;20190:2;20170:18;;;20163:30;20229:29;20209:18;;;20202:57;20276:18;;104562:75:0::1;20123:177:1::0;104562:75:0::1;104650:23;104676:20;104691:4;104676:14;:20::i;:::-;104795:33;::::0;::::1;104707:14;104795:33:::0;;;:17:::1;:33;::::0;;;;;;;;104734:95;;4889:66:1;4876:2;4872:15;;;4868:88;104734:95:0;;::::1;4856:101:1::0;;;;4973:12;;;4966:28;;;5010:12;;;5003:28;;;5047:12;;;5040:28;104650:46:0;;-1:-1:-1;104707:14:0;5084:13:1;;104734:95:0::1;::::0;;;;;::::1;::::0;;;;;;104724:106;;104734:95:::1;104724:106:::0;;::::1;::::0;104841:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;104875:167:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;104724:106;;-1:-1:-1;104841:28:0;104875:167;;;104976:25:::1;104922:15:::0;104996:4;104976:19:::1;:25::i;:::-;104875:167:::0;;::::1;::::0;;::::1;::::0;;;104841:202;;::::1;::::0;;::::1;::::0;;-1:-1:-1;104841:202: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;105148:12;105108:96:::1;::::0;105148:12:::1;;105163:14:::0;105187:4:::1;105194:9:::0;105108:31:::1;:96::i;:::-;105274:23;::::0;:38:::1;::::0;105302:9;105274:27:::1;:38::i;:::-;105248:23;:64:::0;105359:33:::1;::::0;::::1;;::::0;;;:17:::1;:33;::::0;;;;;:48:::1;::::0;105397:9;105359:37:::1;:48::i;:::-;105323:33;::::0;::::1;;::::0;;;:17:::1;:33;::::0;;;;:84;;;;105476:46:::1;::::0;105341:14;;105476:23:::1;:46::i;:::-;105631:35;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;;105627:99:::1;;105673:35;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;105711:15:::1;105673:53:::0;;105627:99:::1;105744:68;::::0;;22959:25:1;;;23015:2;23000:18;;22993:34;;;23043:18;;;23036:34;;;105744:68:0::1;23106:55:1::0;;;23101:2;23086:18;;23079:83;105744:68:0;::::1;::::0;::::1;::::0;22946:3:1;22931:19;105744:68:0::1;;;;;;;104282:1538;;104045:1775:::0;;;;;;;:::o;108446:698::-;108570:31;108545:8;108555:4;88366:42;88390:7;88399:8;88366:23;:42::i;:::-;108705:12:::1;:19:::0;108691:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;108691:34:0::1;;108674:51;;108743:9;108738:339;108762:12;:19:::0;108758:23;::::1;108738:339;;;108823:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;108803:17;;:14;;108841:1;;108803:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;108858:17:::1;::::0;::::1;108881:1;108858:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;108903:12:::1;:15:::0;;108876:1;;108903:15;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;108897:31;;;108929:19;108950:14;108965:1;108950:17;;;;;;;;:::i;:::-;;;;;;;108897:71;;;;;;;;;;;;;;;7029:42:1::0;7017:55;;;;6999:74;;7104:2;7089:18;;7082:34;6987:2;6972:18;;6954:168;108897:71:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;108999:8;108988:77;;;109009:14;109024:1;109009:17;;;;;;;;:::i;:::-;;;;;;;109028:12;109041:1;109028:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;108988:77:::1;::::0;;22154:25:1;;;109028:15:0::1;::::0;;::::1;22256:18:1::0;;;22249:43;;;;22328:15;;22308:18;;;22301:43;22142:2;22127:18;108988:77:0::1;;;;;;;108783:3:::0;::::1;::::0;::::1;:::i;:::-;;;;108738:339;;;-1:-1:-1::0;;;109089:29:0::1;::::0;;::::1;;::::0;;;:19:::1;:29;::::0;;;;109121:15:::1;109089:47:::0;;-1:-1:-1;108446:698:0;:::o;106356:1673::-;106534:47;106545:14;106561:19;106534:10;:47::i;:::-;;106594:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106594:28:0;106655:1;106633:19;;;:23;;;106655:1;106696:283;106720:28;;;;;;;:12;:28;;;;;:35;106716:39;;106696:283;;;106791:28;;;;;;;:12;:28;;;;;:31;;106820:1;;106791:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;106781:6;:48;106777:191;;;106861:28;;;;;;;:12;:28;;;;;:31;;106890:1;;106861:31;;;;;;:::i;:::-;;;;;;;;;;;106849:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106927:1;106911:17;;106947:5;;106777:191;106757:3;;;;:::i;:::-;;;;106696:283;;;-1:-1:-1;106997:16:0;;:26;;106989:54;;;;;;;19807:2:1;106989:54:0;;;19789:21:1;19846:2;19826:18;;;19819:30;19885:17;19865:18;;;19858:45;19920:18;;106989:54:0;19779:165:1;106989:54:0;107081:9;:26;;;107062:15;:45;;:71;;;-1:-1:-1;107111:14:0;;;;:22;;:14;:22;107062:71;:110;;;-1:-1:-1;107153:10:0;107137:27;;;;:15;:27;;;;;;;;:35;;:27;:35;107062:110;107054:145;;;;;;;12598:2:1;107054:145:0;;;12580:21:1;12637:2;12617:18;;;12610:30;12676:24;12656:18;;;12649:52;12718:18;;107054:145:0;12570:172:1;107054:145:0;107232:19;;;;107268:13;;107264:756;;107359:23;;:38;;107387:9;107359:27;:38::i;:::-;107333:23;:64;107448:33;;;;;;;:17;:33;;;;;;:48;;107486:9;107448:37;:48::i;:::-;107412:33;;;;;;;:17;:33;;;;;;;;:84;;;;107568:12;:28;;;:43;;107597:13;;107568:43;;;;;;:::i;:::-;;;;;;;;;;;;;107561:50;;;;;;;;;;;;;;;;;;;;;;;;;;107688:46;;107712:14;;107688:23;:46::i;:::-;107863:12;;;:53;;;;;:12;7017:55:1;;;107863:53:0;;;6999:74:1;;;;7089:18;;;7082:34;;;107863:12:0;;;:21;;6972:18:1;;107863:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;107938:70:0;;;22557:25:1;;;22613:2;22598:18;;22591:34;;;107938:70:0;22661:55:1;;;22641:18;;;22634:83;107938:70:0;;;;;;;;;;;22545:2:1;107938:70:0;;;107264:756;106460:1569;;;106356:1673;;;:::o;97813:133::-;97872:7;97899:39;97908:15;97925:12;;97899:8;:39::i;:::-;97892:46;;97813:133;:::o;109192:1395::-;109293:19;;:51;;;;;109338:4;109293:51;;;6005:74:1;109293:19:0;;;;;:36;;5978:18:1;;109293:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;109705:27;109780:15;;109743:33;109763:12;;109743:15;:19;;:33;;;;:::i;:::-;109735:60;;;;:::i;:::-;109705:90;;109934:9;109929:285;109953:12;:19;109949:23;;109929:285;;;110076:12;110089:1;110076:15;;;;;;;;:::i;:::-;;;;;;;;;;;110070:47;;;;;110111:4;110070:47;;;6005:74:1;110076:15:0;;;;;110070:32;;5978:18:1;;110070:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110002:64;110042:23;:19;110064:1;110042:23;:::i;:::-;110002:35;110021:15;;110002:14;110014:1;110002:11;:14::i;:64::-;:115;;110183:12;110196:1;110183:15;;;;;;;;:::i;:::-;;;;;;;;;;;;110126:73;;;5629:34:1;110126:73:0;;;5617:47:1;;;;5694:6;5680:12;;;5673:28;5739:2;5735:15;;;5717:12;;;5710:110;5836:12;;110126:73:0;;;;;;;;;;;;109994:208;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;109974:3:0;;;;:::i;:::-;;;;109929:285;;;-1:-1:-1;110459:15:0;;110409:67;;110426:49;;110427:26;:19;110451:1;110427:23;:26::i;110426:49::-;110409:12;;;:16;:67::i;:::-;110394:12;:82;110489:29;:27;:29::i;:::-;110565:12;;110536:43;;110565:12;;;;6005:74:1;;110536:43:0;;5993:2:1;5978:18;110536:43:0;5960:125:1;110595:435:0;110682:34;110719:17;:15;:17::i;:::-;110682:54;;110799:9;110794:133;110818:21;:28;110814:32;;110794:133;;;110895:17;110913:1;110895:20;;;;;;;;:::i;:::-;;;;;;;110868:21;110890:1;110868:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;110848:3;;;;:::i;:::-;;;;110794:133;;;;110996:26;:24;:26::i;:::-;110979:14;:43;-1:-1:-1;110595:435:0:o;3172:192::-;3258:7;3294:12;3286:6;;;;3278:29;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;3318:9:0;3330:5;3334:1;3330;:5;:::i;:::-;3318:17;3172:192;-1:-1:-1;;;;;3172:192:0:o;5216:345::-;5302:7;5404:12;5397:5;5389:28;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;5428:9:0;5440:5;5444:1;5440;:5;:::i;101447:1543::-;101637:8;101633:46;;;101661:6;:4;:6::i;:::-;101703:21;;;;101699:1284;;101917:27;101963:28;102010:27;102055:30;102077:7;102055:21;:30::i;:::-;101895:190;;;;;;102147:20;102159:7;102147:11;:20::i;:::-;102243:31;;;;;;;:22;:31;;;;;:54;;;102384:42;;;102380:590;;102447:19;102469:44;:19;102493;102469:23;:44::i;:::-;102557:22;;102447:66;;-1:-1:-1;102557:39:0;;102447:66;102557:26;:39::i;:::-;102532:22;:64;102644:36;:19;102668:11;102644:23;:36::i;:::-;102615:26;;;;;;;:17;:26;;;;;:65;-1:-1:-1;102380:590:0;;;102721:19;102743:44;:19;102767;102743:23;:44::i;:::-;102831:22;;102721:66;;-1:-1:-1;102831:39:0;;102721:66;102831:26;:39::i;:::-;102806:22;:64;102918:36;:19;102942:11;102918:23;:36::i;:::-;102889:26;;;;;;;:17;:26;;;;;:65;-1:-1:-1;101726:1257:0;;;101447:1543;;:::o;38153:402::-;38378:51;;;38367:10;6703:15:1;;;38378:51:0;;;6685:34:1;6755:15;;;6735:18;;;6728:43;6787:18;;;;6780:34;;;38378:51:0;;;;;;;;;;6597:18:1;;;;38378:51:0;;;;;;;;;;;;;38367:63;;-1:-1:-1;;;;38367:10:0;;;;:63;;38378:51;38367:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38331:99;;;;38449:7;:57;;;;-1:-1:-1;38461:11:0;;:16;;:44;;;38492:4;38481:24;;;;;;;;;;;;:::i;:::-;38441:106;;;;;;;20856:2:1;38441:106:0;;;20838:21:1;20895:2;20875:18;;;20868:30;20934:34;20914:18;;;20907:62;21005:6;20985:18;;;20978:34;21029:19;;38441:106:0;20828:226:1;522:106:0;580:7;611:1;607;:5;:13;;619:1;607:13;;;-1:-1:-1;615:1:0;;522:106;-1:-1:-1;522:106:0:o;102998:585::-;103060:21;;;;103056:520;;103137:27;103167:15;103174:7;103167:6;:15::i;:::-;103137:45;;103245:9;103240:118;103264:10;:17;103260:1;:21;103240:118;;;103329:10;103340:1;103329:13;;;;;;;;:::i;:::-;;;;;;;;;;;;103307:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;103324:1;103283:3;103324:1;103283:3;:::i;:::-;;;;103240:118;;;;103425:9;103420:145;103444:10;:17;103440:1;:21;103420:145;;;103525:21;103547:1;103525:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;103487:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;103520:1;103463:3;103520:1;103463:3;:::i;:::-;;;;103420:145;;103056:520;102998:585;:::o;14:196:1:-;82:20;;142:42;131:54;;121:65;;111:2;;200:1;197;190:12;111:2;63:147;;;:::o;215:186::-;274:6;327:2;315:9;306:7;302:23;298:32;295:2;;;343:1;340;333:12;295:2;366:29;385:9;366:29;:::i;406:260::-;474:6;482;535:2;523:9;514:7;510:23;506:32;503:2;;;551:1;548;541:12;503:2;574:29;593:9;574:29;:::i;:::-;564:39;;622:38;656:2;645:9;641:18;622:38;:::i;:::-;612:48;;493:173;;;;;:::o;671:464::-;754:6;762;770;778;831:3;819:9;810:7;806:23;802:33;799:2;;;848:1;845;838:12;799:2;871:29;890:9;871:29;:::i;:::-;861:39;;919:38;953:2;942:9;938:18;919:38;:::i;:::-;909:48;;976:38;1010:2;999:9;995:18;976:38;:::i;:::-;966:48;;1064:2;1053:9;1049:18;1036:32;1077:28;1099:5;1077:28;:::i;:::-;789:346;;;;-1:-1:-1;789:346:1;;-1:-1:-1;;789:346:1:o;1140:254::-;1208:6;1216;1269:2;1257:9;1248:7;1244:23;1240:32;1237:2;;;1285:1;1282;1275:12;1237:2;1308:29;1327:9;1308:29;:::i;:::-;1298:39;1384:2;1369:18;;;;1356:32;;-1:-1:-1;;;1227:167:1:o;1658:383::-;1732:6;1740;1748;1801:2;1789:9;1780:7;1776:23;1772:32;1769:2;;;1817:1;1814;1807:12;1769:2;1840:29;1859:9;1840:29;:::i;:::-;1830:39;;1916:2;1905:9;1901:18;1888:32;1878:42;;1970:2;1959:9;1955:18;1942:32;1983:28;2005:5;1983:28;:::i;:::-;2030:5;2020:15;;;1759:282;;;;;:::o;2046:391::-;2132:6;2140;2148;2156;2209:3;2197:9;2188:7;2184:23;2180:33;2177:2;;;2226:1;2223;2216:12;2177:2;2249:29;2268:9;2249:29;:::i;:::-;2239:39;2325:2;2310:18;;2297:32;;-1:-1:-1;2376:2:1;2361:18;;2348:32;;2427:2;2412:18;2399:32;;-1:-1:-1;2167:270:1;-1:-1:-1;;;2167:270:1:o;2442:241::-;2498:6;2551:2;2539:9;2530:7;2526:23;2522:32;2519:2;;;2567:1;2564;2557:12;2519:2;2606:9;2593:23;2625:28;2647:5;2625:28;:::i;2688:245::-;2755:6;2808:2;2796:9;2787:7;2783:23;2779:32;2776:2;;;2824:1;2821;2814:12;2776:2;2856:9;2850:16;2875:28;2897:5;2875:28;:::i;2938:180::-;2997:6;3050:2;3038:9;3029:7;3025:23;3021:32;3018:2;;;3066:1;3063;3056:12;3018:2;-1:-1:-1;3089:23:1;;3008:110;-1:-1:-1;3008:110:1:o;3308:184::-;3378:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:2;;;3447:1;3444;3437:12;3399:2;-1:-1:-1;3470:16:1;;3389:103;-1:-1:-1;3389:103:1:o;3497:248::-;3565:6;3573;3626:2;3614:9;3605:7;3601:23;3597:32;3594:2;;;3642:1;3639;3632:12;3594:2;-1:-1:-1;;3665:23:1;;;3735:2;3720:18;;;3707:32;;-1:-1:-1;3584:161:1:o;3750:245::-;3829:6;3837;3890:2;3878:9;3869:7;3865:23;3861:32;3858:2;;;3906:1;3903;3896:12;3858:2;-1:-1:-1;;3929:16:1;;3985:2;3970:18;;;3964:25;3929:16;;3964:25;;-1:-1:-1;3848:147:1:o;4000:316::-;4077:6;4085;4093;4146:2;4134:9;4125:7;4121:23;4117:32;4114:2;;;4162:1;4159;4152:12;4114:2;-1:-1:-1;;4185:23:1;;;4255:2;4240:18;;4227:32;;-1:-1:-1;4306:2:1;4291:18;;;4278:32;;4104:212;-1:-1:-1;4104:212:1:o;4321:317::-;4363:3;4401:5;4395:12;4428:6;4423:3;4416:19;4444:63;4500:6;4493:4;4488:3;4484:14;4477:4;4470:5;4466:16;4444:63;:::i;:::-;4552:2;4540:15;4557:66;4536:88;4527:98;;;;4627:4;4523:109;;4371:267;-1:-1:-1;;4371:267:1:o;5108:274::-;5237:3;5275:6;5269:13;5291:53;5337:6;5332:3;5325:4;5317:6;5313:17;5291:53;:::i;:::-;5360:16;;;;;5245:137;-1:-1:-1;;5245:137:1:o;7127:681::-;7298:2;7350:21;;;7420:13;;7323:18;;;7442:22;;;7269:4;;7298:2;7521:15;;;;7495:2;7480:18;;;7269:4;7564:218;7578:6;7575:1;7572:13;7564:218;;;7643:13;;7658:42;7639:62;7627:75;;7757:15;;;;7722:12;;;;7600:1;7593:9;7564:218;;;-1:-1:-1;7799:3:1;;7278:530;-1:-1:-1;;;;;;7278:530:1:o;7813:862::-;7975:4;8004:2;8044;8033:9;8029:18;8074:2;8063:9;8056:21;8097:6;8132;8126:13;8163:6;8155;8148:22;8201:2;8190:9;8186:18;8179:25;;8263:2;8253:6;8250:1;8246:14;8235:9;8231:30;8227:39;8213:53;;8301:2;8293:6;8289:15;8322:1;8332:314;8346:6;8343:1;8340:13;8332:314;;;8435:66;8423:9;8415:6;8411:22;8407:95;8402:3;8395:108;8526:40;8559:6;8550;8544:13;8526:40;:::i;:::-;8516:50;-1:-1:-1;8624:12:1;;;;8589:15;;;;8368:1;8361:9;8332:314;;;-1:-1:-1;8663:6:1;;7984:691;-1:-1:-1;;;;;;;7984:691:1:o;8680:1011::-;8909:2;8961:21;;;9031:13;;8934:18;;;9053:22;;;8880:4;;8909:2;9094;;9112:18;;;;9153:15;;;8880:4;9196:469;9210:6;9207:1;9204:13;9196:469;;;9269:13;;9307:9;;9295:22;;9357:11;;;9351:18;9337:12;;;9330:40;9410:11;;;9404:18;9390:12;;;9383:40;9446:4;9490:11;;;9484:18;9470:12;;;9463:40;9526:4;9570:11;;;9564:18;9550:12;;;9543:40;9612:4;9603:14;;;;9640:15;;;;9232:1;9225:9;9196:469;;;-1:-1:-1;9682:3:1;;8889:802;-1:-1:-1;;;;;;;8889:802:1:o;9696:632::-;9867:2;9919:21;;;9989:13;;9892:18;;;10011:22;;;9838:4;;9867:2;10090:15;;;;10064:2;10049:18;;;9838:4;10133:169;10147:6;10144:1;10141:13;10133:169;;;10208:13;;10196:26;;10277:15;;;;10242:12;;;;10169:1;10162:9;10133:169;;11050:220;11199:2;11188:9;11181:21;11162:4;11219:45;11260:2;11249:9;11245:18;11237:6;11219:45;:::i;23497:128::-;23537:3;23568:1;23564:6;23561:1;23558:13;23555:2;;;23574:18;;:::i;:::-;-1:-1:-1;23610:9:1;;23545:80::o;23630:274::-;23670:1;23696;23686:2;;23731:77;23728:1;23721:88;23832:4;23829:1;23822:15;23860:4;23857:1;23850:15;23686:2;-1:-1:-1;23889:9:1;;23676:228::o;23909:::-;23949:7;24075:1;24007:66;24003:74;24000:1;23997:81;23992:1;23985:9;23978:17;23974:105;23971:2;;;24082:18;;:::i;:::-;-1:-1:-1;24122:9:1;;23961:176::o;24142:125::-;24182:4;24210:1;24207;24204:8;24201:2;;;24215:18;;:::i;:::-;-1:-1:-1;24252:9:1;;24191:76::o;24272:258::-;24344:1;24354:113;24368:6;24365:1;24362:13;24354:113;;;24444:11;;;24438:18;24425:11;;;24418:39;24390:2;24383:10;24354:113;;;24485:6;24482:1;24479:13;24476:2;;;-1:-1:-1;;24520:1:1;24502:16;;24495:27;24325:205::o;24535:437::-;24614:1;24610:12;;;;24657;;;24678:2;;24732:4;24724:6;24720:17;24710:27;;24678:2;24785;24777:6;24774:14;24754:18;24751:38;24748:2;;;24822:77;24819:1;24812:88;24923:4;24920:1;24913:15;24951:4;24948:1;24941:15;24977:195;25016:3;25047:66;25040:5;25037:77;25034:2;;;25117:18;;:::i;:::-;-1:-1:-1;25164:1:1;25153:13;;25024:148::o;25177:184::-;25229:77;25226:1;25219:88;25326:4;25323:1;25316:15;25350:4;25347:1;25340:15;25366:184;25418:77;25415:1;25408:88;25515:4;25512:1;25505:15;25539:4;25536:1;25529:15;25555:184;25607:77;25604:1;25597:88;25704:4;25701:1;25694:15;25728:4;25725:1;25718:15;25744:118;25830:5;25823:13;25816:21;25809:5;25806:32;25796:2;;25852:1;25849;25842:12
Swarm Source
ipfs://92cb052ff4655d13562470bc5cd9a0eb275980daac617e040bce4a52ce186701
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.