Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,878 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Locked | 20766231 | 33 hrs ago | IN | 0 ETH | 0.00076143 | ||||
Withdraw Locked | 20755784 | 2 days ago | IN | 0 ETH | 0.00050436 | ||||
Withdraw Locked | 20753042 | 3 days ago | IN | 0 ETH | 0.00058721 | ||||
Withdraw Locked | 20753038 | 3 days ago | IN | 0 ETH | 0.00063908 | ||||
Withdraw Locked | 20749506 | 3 days ago | IN | 0 ETH | 0.00099477 | ||||
Get Reward | 20749477 | 3 days ago | IN | 0 ETH | 0.00101322 | ||||
Sync | 20602357 | 24 days ago | IN | 0 ETH | 0.00019272 | ||||
Sync | 20530659 | 34 days ago | IN | 0 ETH | 0.00043818 | ||||
Withdraw Locked | 20362023 | 57 days ago | IN | 0 ETH | 0.00309793 | ||||
Get Reward | 20347900 | 59 days ago | IN | 0 ETH | 0.00179283 | ||||
Withdraw Locked | 20310883 | 64 days ago | IN | 0 ETH | 0.00301608 | ||||
Withdraw Locked | 19999261 | 108 days ago | IN | 0 ETH | 0.00190394 | ||||
Get Reward | 19998524 | 108 days ago | IN | 0 ETH | 0.00383866 | ||||
Get Reward | 19982140 | 110 days ago | IN | 0 ETH | 0.00345069 | ||||
Get Reward | 19806022 | 135 days ago | IN | 0 ETH | 0.00354198 | ||||
Sync | 19756485 | 142 days ago | IN | 0 ETH | 0.00101183 | ||||
Get Reward | 19622706 | 161 days ago | IN | 0 ETH | 0.00518261 | ||||
Get Reward | 19558642 | 170 days ago | IN | 0 ETH | 0.00717455 | ||||
Get Reward | 19451118 | 185 days ago | IN | 0 ETH | 0.01185666 | ||||
Withdraw Locked | 19320129 | 203 days ago | IN | 0 ETH | 0.02668377 | ||||
Get Reward | 19320120 | 203 days ago | IN | 0 ETH | 0.03154539 | ||||
Get Reward | 19231468 | 216 days ago | IN | 0 ETH | 0.00907605 | ||||
Get Reward | 19204584 | 219 days ago | IN | 0 ETH | 0.00841493 | ||||
Withdraw Locked | 19181235 | 223 days ago | IN | 0 ETH | 0.01793452 | ||||
Withdraw Locked | 19118168 | 231 days ago | IN | 0 ETH | 0.00868586 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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
[{"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.