Contract
0x57A1CE7686F3B2AB61F5191c76361F985b57E0fa
9
Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
SingleStakingRewards
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at optimistic.etherscan.io on 2022-05-03 */ // SPDX-License-Identifier: BUSL-1.1 // This source code is licensed under the Business Source License // The Licensed Work is (c) 2022 ElkLabs // Full License Text available at https://github.com/elkfinance/elknet-core/blob/main/LICENSE // File: contracts/interfaces/IElkERC20.sol pragma solidity >=0.5.0; interface IElkERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; } // File: @openzeppelin/[email protected]/utils/Address.sol // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/[email protected]/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, 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: @openzeppelin/[email protected]/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @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 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' 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) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: @openzeppelin/[email protected]/security/ReentrancyGuard.sol // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @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() { _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 making 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: @openzeppelin/[email protected]/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @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. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } } // File: @openzeppelin/[email protected]/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/[email protected]/security/Pausable.sol // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: @openzeppelin/[email protected]/access/Ownable.sol // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: contracts/SingleStakingRewardsNewNew.sol pragma solidity >=0.8.0; contract SingleStakingRewards is ReentrancyGuard, Ownable, Pausable { using SafeERC20 for IERC20; /* ========== STATE VARIABLES ========== */ IERC20 public immutable rewardsToken; IERC20 public immutable stakingToken; uint256 public periodFinish; uint256 public rewardRate; uint256 public rewardsDuration; uint256 public lastUpdateTime; uint256 public rewardPerTokenStored; mapping(address => uint256) public userRewardPerTokenPaid; mapping(address => uint256) public rewards; IERC20 public boosterToken; uint256 public boosterRewardRate; uint256 public boosterRewardPerTokenStored; mapping(address => uint256) public userBoosterRewardPerTokenPaid; mapping(address => uint256) public boosterRewards; uint256[] public feeSchedule; uint256[] public withdrawalFeesPct; uint256 public withdrawalFeesUnit = 10000; // unit for fees uint256 public maxWithdrawalFee = 1000; // max withdrawal fee (here, 10%) mapping(address => uint256) public lastStakedTime; uint256 public totalFees; uint256 private _totalSupply; mapping(address => uint256) private _balances; /* ========== CONSTRUCTOR ========== */ constructor( address _rewardsToken, address _stakingToken, address _boosterToken, uint256 _rewardsDuration, uint256[] memory _feeSchedule, // assumes a sorted array uint256[] memory _withdrawalFeesPct // aligned to fee schedule ) { require(_boosterToken != _rewardsToken, "The booster token must be different from the reward token"); require(_boosterToken != _stakingToken, "The booster token must be different from the staking token"); require(_rewardsDuration > 0, "Rewards duration cannot be zero"); rewardsToken = IERC20(_rewardsToken); stakingToken = IERC20(_stakingToken); boosterToken = IERC20(_boosterToken); rewardsDuration = _rewardsDuration; _setWithdrawalFees(_feeSchedule, _withdrawalFeesPct); } /* ========== VIEWS ========== */ function totalSupply() external view returns (uint256) { return _totalSupply; } function balanceOf(address account) external view returns (uint256) { return _balances[account]; } function lastTimeRewardApplicable() public view returns (uint256) { return Math.min(block.timestamp, periodFinish); } function rewardPerToken() public view returns (uint256) { if (_totalSupply == 0) { return rewardPerTokenStored; } return rewardPerTokenStored + (lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * 1e18 / _totalSupply; } function earned(address account) public view returns (uint256) { return _balances[account] * (rewardPerToken() - userRewardPerTokenPaid[account]) / 1e18 + rewards[account]; } function getRewardForDuration() external view returns (uint256) { return rewardRate * rewardsDuration; } function boosterRewardPerToken() public view returns (uint256) { if (_totalSupply == 0) { return boosterRewardPerTokenStored; } return boosterRewardPerTokenStored + (lastTimeRewardApplicable() - lastUpdateTime) * boosterRewardRate * 1e18 / _totalSupply; } function boosterEarned(address account) public view returns (uint256) { return _balances[account] * (boosterRewardPerToken() - userBoosterRewardPerTokenPaid[account]) / 1e18 + boosterRewards[account]; } function getBoosterRewardForDuration() external view returns (uint256) { return boosterRewardRate * rewardsDuration; } function exitFee(address account) external view returns (uint256) { return fee(account, _balances[account]); } function fee(address account, uint256 withdrawalAmount) public view returns (uint256) { for (uint i=0; i < feeSchedule.length; ++i) { if (block.timestamp - lastStakedTime[account] < feeSchedule[i]) { return withdrawalAmount * withdrawalFeesPct[i] / withdrawalFeesUnit; } } return 0; } /* ========== MUTATIVE FUNCTIONS ========== */ function stake(uint256 amount) external nonReentrant whenNotPaused updateReward(msg.sender) { require(amount > 0, "Cannot stake 0"); _totalSupply = _totalSupply + amount; _balances[msg.sender] = _balances[msg.sender] + amount; lastStakedTime[msg.sender] = block.timestamp; stakingToken.safeTransferFrom(msg.sender, address(this), amount); emit Staked(msg.sender, amount); } function stakeWithPermit(uint256 amount, uint deadline, uint8 v, bytes32 r, bytes32 s) external nonReentrant whenNotPaused updateReward(msg.sender) { require(amount > 0, "Cannot stake 0"); _totalSupply = _totalSupply + amount; _balances[msg.sender] = _balances[msg.sender] + amount; // permit IElkERC20(address(stakingToken)).permit(msg.sender, address(this), amount, deadline, v, r, s); lastStakedTime[msg.sender] = block.timestamp; stakingToken.safeTransferFrom(msg.sender, address(this), amount); emit Staked(msg.sender, amount); } function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) { _withdraw(amount); } function emergencyWithdraw(uint256 amount) external nonReentrant { _withdraw(amount); } function _withdraw(uint256 amount) private { require(amount > 0, "Cannot withdraw 0"); uint256 balance = _balances[msg.sender]; require(amount <= balance, "Cannot withdraw more than account balance"); _totalSupply = _totalSupply - amount; uint256 collectedFee = fee(msg.sender, amount); _balances[msg.sender] = balance - amount; uint256 withdrawableBalance = amount - collectedFee; stakingToken.safeTransfer(msg.sender, withdrawableBalance); emit Withdrawn(msg.sender, withdrawableBalance); if (collectedFee > 0) { emit FeesCollected(msg.sender, collectedFee); totalFees = totalFees + collectedFee; } } function getReward() public nonReentrant updateReward(msg.sender) { uint256 reward = rewards[msg.sender]; if (reward > 0) { rewards[msg.sender] = 0; rewardsToken.safeTransfer(msg.sender, reward); emit RewardPaid(msg.sender, reward); } } function getBoosterReward() public nonReentrant updateReward(msg.sender) { if (address(boosterToken) != address(0)) { uint256 reward = boosterRewards[msg.sender]; if (reward > 0) { boosterRewards[msg.sender] = 0; boosterToken.safeTransfer(msg.sender, reward); emit BoosterRewardPaid(msg.sender, reward); } } } function exit() external { withdraw(_balances[msg.sender]); getReward(); getBoosterReward(); } /* ========== RESTRICTED FUNCTIONS ========== */ function sendRewardsAndStartEmission(uint256 reward, uint256 boosterReward, uint256 duration) external onlyOwner { rewardsToken.safeTransferFrom(msg.sender, address(this), reward); if (address(boosterToken) != address(0) && boosterReward > 0) { boosterToken.safeTransferFrom(owner(), address(this), boosterReward); } _startEmission(reward, boosterReward, duration); } function startEmission(uint256 reward, uint256 boosterReward, uint256 duration) external onlyOwner { _startEmission(reward, boosterReward, duration); } function stopEmission() external onlyOwner { require(block.timestamp < periodFinish, "Cannot stop rewards emissions if not started or already finished"); uint256 tokensToBurn; uint256 boosterTokensToBurn; if (_totalSupply == 0) { tokensToBurn = rewardsToken.balanceOf(address(this)); if (address(boosterToken) != address(0)) { boosterTokensToBurn = boosterToken.balanceOf(address(this)); } else { boosterTokensToBurn = 0; } } else { uint256 remaining = periodFinish - block.timestamp; tokensToBurn = rewardRate * remaining; boosterTokensToBurn = boosterRewardRate * remaining; } periodFinish = block.timestamp; if (tokensToBurn > 0) { rewardsToken.safeTransfer(owner(), tokensToBurn); } if (address(boosterToken) != address(0) && boosterTokensToBurn > 0) { boosterToken.safeTransfer(owner(), boosterTokensToBurn); } emit RewardsEmissionEnded(tokensToBurn); } function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner { IERC20(tokenAddress).safeTransfer(msg.sender, tokenAmount); emit Recovered(tokenAddress, tokenAmount); } function recoverLeftoverReward() external onlyOwner { require(_totalSupply == 0 && rewardsToken == stakingToken, "Cannot recover leftover reward if it is not the staking token or there are still staked tokens"); uint256 tokensToBurn = rewardsToken.balanceOf(address(this)); if (tokensToBurn > 0) { rewardsToken.safeTransfer(msg.sender, tokensToBurn); } emit LeftoverRewardRecovered(tokensToBurn); } function recoverLeftoverBooster() external onlyOwner { require(address(boosterToken) != address(0), "Cannot recover leftover booster if there was no booster token set"); require(_totalSupply == 0, "Cannot recover leftover booster if there are still staked tokens"); uint256 tokensToBurn = boosterToken.balanceOf(address(this)); if (tokensToBurn > 0) { boosterToken.safeTransfer(msg.sender, tokensToBurn); } emit LeftoverBoosterRecovered(tokensToBurn); } function recoverFees() external onlyOwner { uint256 previousFees = totalFees; totalFees = 0; stakingToken.safeTransfer(owner(), previousFees); emit FeesRecovered(previousFees); } function setRewardsDuration(uint256 duration) external onlyOwner { require( block.timestamp > periodFinish, "Previous rewards period must be complete before changing the duration for the new period" ); _setRewardsDuration(duration); } // Booster Rewards function setBoosterToken(address _boosterToken) external onlyOwner { require(_boosterToken != address(rewardsToken), "The booster token must be different from the reward token"); require(_boosterToken != address(stakingToken), "The booster token must be different from the staking token"); boosterToken = IERC20(_boosterToken); emit BoosterRewardSet(_boosterToken); } function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } // Withdrawal Fees function setWithdrawalFees(uint256[] memory _feeSchedule, uint256[] memory _withdrawalFees) external onlyOwner { _setWithdrawalFees(_feeSchedule, _withdrawalFees); } // Private functions function _setRewardsDuration(uint256 duration) private { rewardsDuration = duration; emit RewardsDurationUpdated(rewardsDuration); } function _setWithdrawalFees(uint256[] memory _feeSchedule, uint256[] memory _withdrawalFeesPct) private { require(_feeSchedule.length == _withdrawalFeesPct.length, "Fee schedule and withdrawal fees arrays must be the same length!"); require(_feeSchedule.length <= 10, "Fee schedule and withdrawal fees arrays lengths cannot be larger than 10!"); uint256 lastFeeSchedule = 0; uint256 lastWithdrawalFee = maxWithdrawalFee + 1; for(uint256 i = 0; i < _feeSchedule.length; ++i) { require(_feeSchedule[i] > lastFeeSchedule, "Fee schedule must be ascending!"); require(_withdrawalFeesPct[i] < lastWithdrawalFee, "Withdrawal fees must be descending and lower than maximum!"); lastFeeSchedule = _feeSchedule[i]; lastWithdrawalFee = _withdrawalFeesPct[i]; } feeSchedule = _feeSchedule; withdrawalFeesPct = _withdrawalFeesPct; emit WithdrawalFeesSet(_feeSchedule, _withdrawalFeesPct); } // Must send reward before calling this! function _startEmission(uint256 reward, uint256 boosterReward, uint256 duration) private updateReward(address(0)) { if (duration > 0) { _setRewardsDuration(duration); } if (block.timestamp >= periodFinish) { rewardRate = reward / rewardsDuration; boosterRewardRate = boosterReward / rewardsDuration; } else { uint256 remaining = periodFinish - block.timestamp; uint256 leftover = remaining * rewardRate; rewardRate = (reward + leftover) / rewardsDuration; uint256 boosterLeftover = remaining * boosterRewardRate; boosterRewardRate = (boosterReward + boosterLeftover) / rewardsDuration; } // 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. uint balance = rewardsToken.balanceOf(address(this)); if (rewardsToken != stakingToken) { require(rewardRate <= balance / rewardsDuration, "Provided reward too high"); } else { // Handle care where rewardsToken is the same as stakingToken (need to subtract total supply) require(rewardRate <= (balance - _totalSupply) / rewardsDuration, "Provided reward too high"); } if (address(boosterToken) != address(0)) { uint boosterBalance = boosterToken.balanceOf(address(this)); require(boosterRewardRate <= boosterBalance / rewardsDuration, "Provided booster reward too high"); } lastUpdateTime = block.timestamp; periodFinish = block.timestamp + rewardsDuration; emit RewardsEmissionStarted(reward, boosterReward, duration); } /* ========== MODIFIERS ========== */ modifier updateReward(address account) { rewardPerTokenStored = rewardPerToken(); boosterRewardPerTokenStored = boosterRewardPerToken(); lastUpdateTime = lastTimeRewardApplicable(); if (account != address(0)) { rewards[account] = earned(account); userRewardPerTokenPaid[account] = rewardPerTokenStored; boosterRewards[account] = boosterEarned(account); userBoosterRewardPerTokenPaid[account] = boosterRewardPerTokenStored; } _; } /* ========== EVENTS ========== */ event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event BoosterRewardPaid(address indexed user, uint256 reward); event RewardsDurationUpdated(uint256 newDuration); event Recovered(address token, uint256 amount); event LeftoverRewardRecovered(uint256 amount); event LeftoverBoosterRecovered(uint256 amount); event RewardsEmissionStarted(uint256 reward, uint256 boosterReward, uint256 duration); event RewardsEmissionEnded(uint256 amount); event BoosterRewardSet(address token); event WithdrawalFeesSet(uint256[] _feeSchedule, uint256[] _withdrawalFees); event FeesCollected(address indexed user, uint256 amount); event FeesRecovered(uint256 amount); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_boosterToken","type":"address"},{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"},{"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"internalType":"uint256[]","name":"_withdrawalFeesPct","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"BoosterRewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"BoosterRewardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LeftoverBoosterRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LeftoverRewardRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"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"}],"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":"uint256","name":"amount","type":"uint256"}],"name":"RewardsEmissionEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boosterReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"RewardsEmissionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"_withdrawalFees","type":"uint256[]"}],"name":"WithdrawalFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"boosterEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"boosterRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"exitFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"withdrawalAmount","type":"uint256"}],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"feeSchedule","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBoosterReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBoosterRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastStakedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWithdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"recoverFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLeftoverBooster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLeftoverReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"boosterReward","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"sendRewardsAndStartEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_boosterToken","type":"address"}],"name":"setBoosterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"internalType":"uint256[]","name":"_withdrawalFees","type":"uint256[]"}],"name":"setWithdrawalFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"stakeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"boosterReward","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"startEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBoosterRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalFeesPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalFeesUnit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040526127106010556103e86011553480156200001d57600080fd5b5060405162003dc238038062003dc283398101604081905262000040916200063d565b60016000556200005033620001e5565b6001805460ff60a01b191690556001600160a01b0380871690851603620000d35760405162461bcd60e51b8152602060048201526039602482015260008051602062003da283398151915260448201527f656e742066726f6d207468652072657761726420746f6b656e0000000000000060648201526084015b60405180910390fd5b846001600160a01b0316846001600160a01b0316036200014b5760405162461bcd60e51b815260206004820152603a602482015260008051602062003da283398151915260448201527f656e742066726f6d20746865207374616b696e6720746f6b656e0000000000006064820152608401620000ca565b600083116200019d5760405162461bcd60e51b815260206004820152601f60248201527f52657761726473206475726174696f6e2063616e6e6f74206265207a65726f006044820152606401620000ca565b6001600160a01b0386811660805285811660a052600980546001600160a01b0319169186169190911790556004839055620001d9828262000237565b505050505050620007ba565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8051825114620002a1576040805162461bcd60e51b815260206004820152602481019190915260008051602062003d8283398151915260448201527f20617272617973206d757374206265207468652073616d65206c656e677468216064820152608401620000ca565b600a825111156200031c5760405162461bcd60e51b8152602060048201526049602482015260008051602062003d8283398151915260448201527f20617272617973206c656e677468732063616e6e6f74206265206c6172676572606482015268207468616e2031302160b81b608482015260a401620000ca565b6000806011546001620003309190620006fe565b905060005b845181101562000491578285828151811062000355576200035562000719565b602002602001015111620003ac5760405162461bcd60e51b815260206004820152601f60248201527f466565207363686564756c65206d75737420626520617363656e64696e6721006044820152606401620000ca565b81848281518110620003c257620003c262000719565b6020026020010151106200043f5760405162461bcd60e51b815260206004820152603a60248201527f5769746864726177616c2066656573206d7573742062652064657363656e646960448201527f6e6720616e64206c6f776572207468616e206d6178696d756d210000000000006064820152608401620000ca565b84818151811062000454576200045462000719565b6020026020010151925083818151811062000473576200047362000719565b602002602001015191508062000489906200072f565b905062000335565b508351620004a790600e906020870190620004ff565b508251620004bd90600f906020860190620004ff565b507fe5a2c1e4acf2a2da539a1183c56fbbcec4b66dbc828b76f1c1bf365f1887886b8484604051620004f192919062000788565b60405180910390a150505050565b8280548282559060005260206000209081019282156200053d579160200282015b828111156200053d57825182559160200191906001019062000520565b506200054b9291506200054f565b5090565b5b808211156200054b576000815560010162000550565b80516001600160a01b03811681146200057e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620005ab57600080fd5b815160206001600160401b0380831115620005ca57620005ca62000583565b8260051b604051601f19603f83011681018181108482111715620005f257620005f262000583565b6040529384528581018301938381019250878511156200061157600080fd5b83870191505b84821015620006325781518352918301919083019062000617565b979650505050505050565b60008060008060008060c087890312156200065757600080fd5b620006628762000566565b9550620006726020880162000566565b9450620006826040880162000566565b6060880151608089015191955093506001600160401b0380821115620006a757600080fd5b620006b58a838b0162000599565b935060a0890151915080821115620006cc57600080fd5b50620006db89828a0162000599565b9150509295509295509295565b634e487b7160e01b600052601160045260246000fd5b60008219821115620007145762000714620006e8565b500190565b634e487b7160e01b600052603260045260246000fd5b600060018201620007445762000744620006e8565b5060010190565b600081518084526020808501945080840160005b838110156200077d578151875295820195908201906001016200075f565b509495945050505050565b6040815260006200079d60408301856200074b565b8281036020840152620007b181856200074b565b95945050505050565b60805160a0516135246200085e6000396000818161050f01528181610c840152818161160f0152818161199e01528181611bc201528181611e7301528181611ee60152818161242c0152612ae601526000818161066d0152818161086d015281816109cc01528181610cae01528181610d8801528181610e10015281816110dc0152818161134d0152818161156801528181612a6f0152612b1001526135246000f3fe608060405234801561001057600080fd5b50600436106103615760003560e01c80637b0a47ee116101c8578063c8f33c9111610104578063ebe2b12b116100a2578063f22797d81161007c578063f22797d8146106c5578063f2fde38b146106e5578063f3f0ffda146106f8578063faef375e1461070057600080fd5b8063ebe2b12b146106a0578063ec1c0a99146106a9578063ecd9ba82146106b257600080fd5b8063cdeae371116100de578063cdeae37114610660578063d1af0c7d14610668578063df136d651461068f578063e9fad8ee1461069857600080fd5b8063c8f33c911461063c578063cc1a378f14610645578063cd3daf9d1461065857600080fd5b80638da5cb5b116101715780639e6eda181161014b5780639e6eda18146105ed578063a694fc3a14610600578063be0bf75114610613578063c57a202c1461061c57600080fd5b80638da5cb5b146105b65780638f0bb79c146105c75780639465d4a1146105da57600080fd5b80638980f11f116101a25780638980f11f146105705780638b876347146105835780638bb95b45146105a357600080fd5b80637b0a47ee1461055757806380faa57d146105605780638456cb591461056857600080fd5b80633b8e4f7e116102a25780636439ea4c11610240578063715018a61161021a578063715018a61461050257806372f702f31461050a5780637707513014610531578063771916051461054457600080fd5b80636439ea4c146104c857806366a03c7f146104d057806370a08231146104d957600080fd5b80635312ea8e1161027c5780635312ea8e1461044d578063576c23ab146104605780635c975abb1461048b5780635d129544146104a857600080fd5b80633b8e4f7e1461042a5780633d18b9121461043d5780633f4ba83a1461044557600080fd5b80631c1f78eb1161030f5780632e1a7d4d116102e95780632e1a7d4d146103f257806335ceec0f14610405578063386a9525146104185780633b7d27fe1461042157600080fd5b80631c1f78eb146103da5780632459a699146103e25780632cbe61d3146103ea57600080fd5b806310cbbe381161034057806310cbbe38146103b657806313114a9d146103c957806318160ddd146103d257600080fd5b80628cc262146103665780630700037d1461038c5780630e9bb0a3146103ac575b600080fd5b610379610374366004613117565b610708565b6040519081526020015b60405180910390f35b61037961039a366004613117565b60086020526000908152604090205481565b6103b4610785565b005b6103796103c4366004613117565b610a72565b61037960135481565b601454610379565b610379610a96565b6103b4610aad565b6103b4610c2f565b6103b4610400366004613132565b610e6e565b610379610413366004613132565b610f68565b61037960045481565b61037960105481565b610379610438366004613117565b610f89565b6103b4610fbf565b6103b461113d565b6103b461045b366004613132565b61118f565b600954610473906001600160a01b031681565b6040516001600160a01b039091168152602001610383565b600154600160a01b900460ff166040519015158152602001610383565b6103796104b6366004613117565b600c6020526000908152604090205481565b6103796111ef565b610379600b5481565b6103796104e7366004613117565b6001600160a01b031660009081526015602052604090205490565b6103b4611250565b6104737f000000000000000000000000000000000000000000000000000000000000000081565b6103b461053f3660046131f1565b6112a2565b6103b4610552366004613255565b6112f8565b61037960035481565b6103796113cd565b6103b46113db565b6103b461057e366004613281565b61142b565b610379610591366004613117565b60076020526000908152604090205481565b6103b46105b1366004613255565b6114c6565b6001546001600160a01b0316610473565b6103796105d5366004613132565b61150e565b6103b46105e8366004613117565b61151e565b6103796105fb366004613281565b61170f565b6103b461060e366004613132565b6117bd565b610379600a5481565b61037961062a366004613117565b60126020526000908152604090205481565b61037960055481565b6103b4610653366004613132565b611a00565b610379611af1565b6103b4611b52565b6104737f000000000000000000000000000000000000000000000000000000000000000081565b61037960065481565b6103b4611c19565b61037960025481565b61037960115481565b6103b46106c03660046132ab565b611c42565b6103796106d3366004613117565b600d6020526000908152604090205481565b6103b46106f3366004613117565b611f59565b610379612026565b6103b4612038565b6001600160a01b0381166000908152600860209081526040808320546007909252822054670de0b6b3a76400009061073e611af1565b6107489190613310565b6001600160a01b03851660009081526015602052604090205461076b9190613327565b6107759190613346565b61077f9190613368565b92915050565b6001546001600160a01b031633146107d25760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064015b60405180910390fd5b600254421061084b576040805162461bcd60e51b81526020600482015260248101919091527f43616e6e6f742073746f70207265776172647320656d697373696f6e7320696660448201527f206e6f742073746172746564206f7220616c72656164792066696e697368656460648201526084016107c9565b60008060145460000361096f576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156108bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e09190613380565b6009549092506001600160a01b031615610967576009546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561093c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109609190613380565b90506109a3565b5060006109a3565b60004260025461097f9190613310565b90508060035461098f9190613327565b925080600a5461099f9190613327565b9150505b4260025581156109f3576109f36109c26001546001600160a01b031690565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169084612258565b6009546001600160a01b031615801590610a0d5750600081115b15610a3a57610a3a610a276001546001600160a01b031690565b6009546001600160a01b03169083612258565b6040518281527f6d815f6a8a51efb6f4140923189859b9e9caaa228c9334179e8eb7edefc6838e906020015b60405180910390a15050565b6001600160a01b03811660009081526015602052604081205461077f90839061170f565b6000600454600354610aa89190613327565b905090565b600260005403610aff5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b600260005533610b0d611af1565b600655610b186111ef565b600b55610b236113cd565b6005556001600160a01b03811615610b9e57610b3e81610708565b6001600160a01b038216600090815260086020908152604080832093909355600654600790915291902055610b7281610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b6009546001600160a01b031615610c2757336000908152600d60205260409020548015610c2557336000818152600d6020526040812055600954610bee916001600160a01b039091169083612258565b60405181815233907fd1e5531ac01ffc9c7971b52c82806a6e5ae8907ddedd2e3153afaafcfdf175d6906020015b60405180910390a25b505b506001600055565b6001546001600160a01b03163314610c775760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b601454158015610cd857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316145b610d705760405162461bcd60e51b815260206004820152605e60248201527f43616e6e6f74207265636f766572206c6566746f76657220726577617264206960448201527f66206974206973206e6f7420746865207374616b696e6720746f6b656e206f7260648201527f20746865726520617265207374696c6c207374616b656420746f6b656e730000608482015260a4016107c9565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190613380565b90508015610e3757610e376001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612258565b6040518181527ff6d91c6a1bf05d7c0f2c157905a97d3bc2f860a1402d71dd52a27fabb5bcaf8d906020015b60405180910390a150565b600260005403610ec05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b600260005533610ece611af1565b600655610ed96111ef565b600b55610ee46113cd565b6005556001600160a01b03811615610f5f57610eff81610708565b6001600160a01b038216600090815260086020908152604080832093909355600654600790915291902055610f3381610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b610c2582612301565b600e8181548110610f7857600080fd5b600091825260209091200154905081565b6001600160a01b0381166000908152600d6020908152604080832054600c909252822054670de0b6b3a76400009061073e6111ef565b6002600054036110115760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b60026000553361101f611af1565b60065561102a6111ef565b600b556110356113cd565b6005556001600160a01b038116156110b05761105081610708565b6001600160a01b03821660009081526008602090815260408083209390935560065460079091529190205561108481610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b336000908152600860205260409020548015610c25573360008181526008602052604081205561110b907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169083612258565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048690602001610c1c565b6001546001600160a01b031633146111855760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b61118d6124db565b565b6002600054036111e15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b6002600055610c2781612301565b60006014546000036112025750600b5490565b601454600a546005546112136113cd565b61121d9190613310565b6112279190613327565b61123990670de0b6b3a7640000613327565b6112439190613346565b600b54610aa89190613368565b6001546001600160a01b031633146112985760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b61118d6000612581565b6001546001600160a01b031633146112ea5760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6112f482826125e0565b5050565b6001546001600160a01b031633146113405760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6113756001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330866128be565b6009546001600160a01b03161580159061138f5750600082115b156113bd576113bd6113a96001546001600160a01b031690565b6009546001600160a01b03169030856128be565b6113c883838361290f565b505050565b6000610aa842600254612d49565b6001546001600160a01b031633146114235760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b61118d612d61565b6001546001600160a01b031633146114735760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6114876001600160a01b0383163383612258565b604080516001600160a01b0384168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101610a66565b6001546001600160a01b031633146113bd5760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b600f8181548110610f7857600080fd5b6001546001600160a01b031633146115665760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03160361160d5760405162461bcd60e51b815260206004820152603960248201527f54686520626f6f7374657220746f6b656e206d7573742062652064696666657260448201527f656e742066726f6d207468652072657761726420746f6b656e0000000000000060648201526084016107c9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036116b45760405162461bcd60e51b815260206004820152603a60248201527f54686520626f6f7374657220746f6b656e206d7573742062652064696666657260448201527f656e742066726f6d20746865207374616b696e6720746f6b656e00000000000060648201526084016107c9565b6009805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f0c6fec5b80219c372da56cb4d1ef3e172069953fa5c72ececf0d0dfe1109260b90602001610e63565b6000805b600e548110156117b357600e818154811061173057611730613399565b60009182526020808320909101546001600160a01b0387168352601290915260409091205461175f9042613310565b10156117a357601054600f828154811061177b5761177b613399565b9060005260206000200154846117919190613327565b61179b9190613346565b91505061077f565b6117ac816133af565b9050611713565b5060009392505050565b60026000540361180f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b6002600055600154600160a01b900460ff16156118615760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016107c9565b3361186a611af1565b6006556118756111ef565b600b556118806113cd565b6005556001600160a01b038116156118fb5761189b81610708565b6001600160a01b0382166000908152600860209081526040808320939093556006546007909152919020556118cf81610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b6000821161194b5760405162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b65203000000000000000000000000000000000000060448201526064016107c9565b816014546119599190613368565b60145533600090815260156020526040902054611977908390613368565b3360008181526015602090815260408083209490945560129052919091204290556119ce907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169030856128be565b60405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90602001610c1c565b6001546001600160a01b03163314611a485760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6002544211611ae55760405162461bcd60e51b815260206004820152605860248201527f50726576696f7573207265776172647320706572696f64206d7573742062652060448201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260648201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000608482015260a4016107c9565b611aee81612de9565b50565b6000601454600003611b04575060065490565b601454600354600554611b156113cd565b611b1f9190613310565b611b299190613327565b611b3b90670de0b6b3a7640000613327565b611b459190613346565b600654610aa89190613368565b6001546001600160a01b03163314611b9a5760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b601380546000909155611be9611bb86001546001600160a01b031690565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083612258565b6040518181527f6857c770f3cb43e9c19050a37dd914ec876241c1f4b487d26a1d4f5d3054f49b90602001610e63565b33600090815260156020526040902054611c3290610e6e565b611c3a610fbf565b61118d610aad565b600260005403611c945760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107c9565b6002600055600154600160a01b900460ff1615611ce65760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016107c9565b33611cef611af1565b600655611cfa6111ef565b600b55611d056113cd565b6005556001600160a01b03811615611d8057611d2081610708565b6001600160a01b038216600090815260086020908152604080832093909355600654600790915291902055611d5481610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b60008611611dd05760405162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b65203000000000000000000000000000000000000060448201526064016107c9565b85601454611dde9190613368565b60145533600090815260156020526040902054611dfc908790613368565b33600081815260156020526040908190209290925590517fd505accf0000000000000000000000000000000000000000000000000000000081526004810191909152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d505accf9060e401600060405180830381600087803b158015611eb757600080fd5b505af1158015611ecb573d6000803e3d6000fd5b5050336000818152601260205260409020429055611f1792507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316915030896128be565b60405186815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a25050600160005550505050565b6001546001600160a01b03163314611fa15760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6001600160a01b03811661201d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107c9565b611aee81612581565b6000600454600a54610aa89190613327565b6001546001600160a01b031633146120805760405162461bcd60e51b815260206004820181905260248201526000805160206134cf83398151915260448201526064016107c9565b6009546001600160a01b03166121245760405162461bcd60e51b815260206004820152604160248201527f43616e6e6f74207265636f766572206c6566746f76657220626f6f737465722060448201527f696620746865726520776173206e6f20626f6f7374657220746f6b656e20736560648201527f7400000000000000000000000000000000000000000000000000000000000000608482015260a4016107c9565b6014541561219c576040805162461bcd60e51b81526020600482015260248101919091527f43616e6e6f74207265636f766572206c6566746f76657220626f6f737465722060448201527f696620746865726520617265207374696c6c207374616b656420746f6b656e7360648201526084016107c9565b6009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156121e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122099190613380565b9050801561222857600954612228906001600160a01b03163383612258565b6040518181527fa075ee3dcd38efb87f0f97160a935b6a43768378263338beea06b9681f66151d90602001610e63565b6040516001600160a01b0383166024820152604481018290526113c89084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e1e565b600081116123515760405162461bcd60e51b815260206004820152601160248201527f43616e6e6f74207769746864726177203000000000000000000000000000000060448201526064016107c9565b33600090815260156020526040902054808211156123d75760405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207769746864726177206d6f7265207468616e206163636f756e60448201527f742062616c616e6365000000000000000000000000000000000000000000000060648201526084016107c9565b816014546123e59190613310565b60145560006123f4338461170f565b90506124008383613310565b3360009081526015602052604081209190915561241d8285613310565b90506124536001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612258565b60405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a281156124d55760405182815233907f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce9060200160405180910390a2816013546124d19190613368565b6013555b50505050565b600154600160a01b900460ff166125345760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016107c9565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600180546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8051825114612659576040805162461bcd60e51b81526020600482015260248101919091527f466565207363686564756c6520616e64207769746864726177616c206665657360448201527f20617272617973206d757374206265207468652073616d65206c656e6774682160648201526084016107c9565b600a825111156126f75760405162461bcd60e51b815260206004820152604960248201527f466565207363686564756c6520616e64207769746864726177616c206665657360448201527f20617272617973206c656e677468732063616e6e6f74206265206c617267657260648201527f207468616e203130210000000000000000000000000000000000000000000000608482015260a4016107c9565b60008060115460016127099190613368565b905060005b8451811015612856578285828151811061272a5761272a613399565b60200260200101511161277f5760405162461bcd60e51b815260206004820152601f60248201527f466565207363686564756c65206d75737420626520617363656e64696e67210060448201526064016107c9565b8184828151811061279257612792613399565b60200260200101511061280d5760405162461bcd60e51b815260206004820152603a60248201527f5769746864726177616c2066656573206d7573742062652064657363656e646960448201527f6e6720616e64206c6f776572207468616e206d6178696d756d2100000000000060648201526084016107c9565b84818151811061281f5761281f613399565b6020026020010151925083818151811061283b5761283b613399565b602002602001015191508061284f906133af565b905061270e565b50835161286a90600e90602087019061309b565b50825161287e90600f90602086019061309b565b507fe5a2c1e4acf2a2da539a1183c56fbbcec4b66dbc828b76f1c1bf365f1887886b84846040516128b0929190613403565b60405180910390a150505050565b6040516001600160a01b03808516602483015283166044820152606481018290526124d59085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161229d565b6000612919611af1565b6006556129246111ef565b600b5561292f6113cd565b6005556001600160a01b038116156129aa5761294a81610708565b6001600160a01b03821660009081526008602090815260408083209390935560065460079091529190205561297e81610f89565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b81156129b9576129b982612de9565b60025442106129e7576004546129cf9085613346565b6003556004546129df9084613346565b600a55612a57565b6000426002546129f79190613310565b9050600060035482612a099190613327565b600454909150612a198288613368565b612a239190613346565b600355600a54600090612a369084613327565b600454909150612a468288613368565b612a509190613346565b600a555050505b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612abe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae29190613380565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612ba057600454612b4a9082613346565b6003541115612b9b5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f2068696768000000000000000060448201526064016107c9565b612c0b565b600454601454612bb09083613310565b612bba9190613346565b6003541115612c0b5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f2068696768000000000000000060448201526064016107c9565b6009546001600160a01b031615612cec576009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612c65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c899190613380565b905060045481612c999190613346565b600a541115612cea5760405162461bcd60e51b815260206004820181905260248201527f50726f766964656420626f6f737465722072657761726420746f6f206869676860448201526064016107c9565b505b426005819055600454612cfe91613368565b60025560408051868152602081018690529081018490527f748824204e79acdab8f1a9977cbc584250e206ad90d05ef198799f9d6ee93a7d9060600160405180910390a15050505050565b6000818310612d585781612d5a565b825b9392505050565b600154600160a01b900460ff1615612dae5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016107c9565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125643390565b60048190556040518181527ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d390602001610e63565b6000612e73826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f039092919063ffffffff16565b8051909150156113c85780806020019051810190612e919190613431565b6113c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107c9565b6060612f128484600085612f1a565b949350505050565b606082471015612f925760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107c9565b6001600160a01b0385163b612fe95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107c9565b600080866001600160a01b03168587604051613005919061347f565b60006040518083038185875af1925050503d8060008114613042576040519150601f19603f3d011682016040523d82523d6000602084013e613047565b606091505b5091509150613057828286613062565b979650505050505050565b60608315613071575081612d5a565b8251156130815782518084602001fd5b8160405162461bcd60e51b81526004016107c9919061349b565b8280548282559060005260206000209081019282156130d6579160200282015b828111156130d65782518255916020019190600101906130bb565b506130e29291506130e6565b5090565b5b808211156130e257600081556001016130e7565b80356001600160a01b038116811461311257600080fd5b919050565b60006020828403121561312957600080fd5b612d5a826130fb565b60006020828403121561314457600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261317257600080fd5b8135602067ffffffffffffffff8083111561318f5761318f61314b565b8260051b604051601f19603f830116810181811084821117156131b4576131b461314b565b6040529384528581018301938381019250878511156131d257600080fd5b83870191505b84821015613057578135835291830191908301906131d8565b6000806040838503121561320457600080fd5b823567ffffffffffffffff8082111561321c57600080fd5b61322886838701613161565b9350602085013591508082111561323e57600080fd5b5061324b85828601613161565b9150509250929050565b60008060006060848603121561326a57600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561329457600080fd5b61329d836130fb565b946020939093013593505050565b600080600080600060a086880312156132c357600080fd5b8535945060208601359350604086013560ff811681146132e257600080fd5b94979396509394606081013594506080013592915050565b634e487b7160e01b600052601160045260246000fd5b600082821015613322576133226132fa565b500390565b6000816000190483118215151615613341576133416132fa565b500290565b60008261336357634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561337b5761337b6132fa565b500190565b60006020828403121561339257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000600182016133c1576133c16132fa565b5060010190565b600081518084526020808501945080840160005b838110156133f8578151875295820195908201906001016133dc565b509495945050505050565b60408152600061341660408301856133c8565b828103602084015261342881856133c8565b95945050505050565b60006020828403121561344357600080fd5b81518015158114612d5a57600080fd5b60005b8381101561346e578181015183820152602001613456565b838111156124d55750506000910152565b60008251613491818460208701613453565b9190910192915050565b60208152600082518060208401526134ba816040850160208701613453565b601f01601f1916919091016040019291505056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220f1782956c14f05a3ad891819b987778508dbc25a816f61f86c1be51a059aafaa64736f6c634300080d0033466565207363686564756c6520616e64207769746864726177616c206665657354686520626f6f7374657220746f6b656e206d75737420626520646966666572000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000278d00000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000064
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000278d00000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000064
-----Decoded View---------------
Arg [0] : _rewardsToken (address): 0xeeeeeb57642040be42185f49c52f7e9b38f8eeee
Arg [1] : _stakingToken (address): 0xeeeeeb57642040be42185f49c52f7e9b38f8eeee
Arg [2] : _boosterToken (address): 0x0000000000000000000000000000000000000000
Arg [3] : _rewardsDuration (uint256): 1814400
Arg [4] : _feeSchedule (uint256[]): 3600,604800,2592000
Arg [5] : _withdrawalFeesPct (uint256[]): 500,200,100
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee
Arg [1] : 000000000000000000000000eeeeeb57642040be42185f49c52f7e9b38f8eeee
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 00000000000000000000000000000000000000000000000000000000001baf80
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000e10
Arg [8] : 0000000000000000000000000000000000000000000000000000000000093a80
Arg [9] : 0000000000000000000000000000000000000000000000000000000000278d00
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [11] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [12] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000064
Deployed ByteCode Sourcemap
26781:16289:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29579:188;;;;;;:::i;:::-;;:::i;:::-;;;552:25:1;;;540:2;525:18;29579:188:0;;;;;;;;27275:42;;;;;;:::i;:::-;;;;;;;;;;;;;;34700:1130;;;:::i;:::-;;30573:124;;;;;;:::i;:::-;;:::i;27857:24::-;;;;;;28926:93;28999:12;;28926:93;;29775:118;;;:::i;33478:422::-;;;:::i;36059:461::-;;;:::i;32191:115::-;;;;;;:::i;:::-;;:::i;27578:28::-;;;;;;:::i;:::-;;:::i;27094:30::-;;;;;;27654:41;;;;;;30209:216;;;;;;:::i;:::-;;:::i;33163:307::-;;;:::i;38101:67::-;;;:::i;32314:101::-;;;;;;:::i;:::-;;:::i;27326:26::-;;;;;-1:-1:-1;;;;;27326:26:0;;;;;;-1:-1:-1;;;;;951:55:1;;;933:74;;921:2;906:18;27326:26:0;773:240:1;22962:86:0;23033:7;;-1:-1:-1;;;23033:7:0;;;;22962:86;;1183:14:1;;1176:22;1158:41;;1146:2;1131:18;22962:86:0;1018:187:1;27449:64:0;;;;;;:::i;:::-;;;;;;;;;;;;;;29901:300;;;:::i;27398:42::-;;;;;;29027:112;;;;;;:::i;:::-;-1:-1:-1;;;;;29113:18:0;29086:7;29113:18;;;:9;:18;;;;;;;29027:112;25867:103;;;:::i;26985:36::-;;;;;38202:179;;;;;;:::i;:::-;;:::i;34098:421::-;;;;;;:::i;:::-;;:::i;27062:25::-;;;;;;29147:131;;;:::i;38030:63::-;;;:::i;35838:213::-;;;;;;:::i;:::-;;:::i;27211:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;34527:165;;;;;;:::i;:::-;;:::i;25216:87::-;25289:6;;-1:-1:-1;;;;;25289:6:0;25216:87;;27613:34;;;;;;:::i;:::-;;:::i;37614:408::-;;;;;;:::i;:::-;;:::i;30705:359::-;;;;;;:::i;:::-;;:::i;31126:432::-;;;;;;:::i;:::-;;:::i;27359:32::-;;;;;;27801:49;;;;;;:::i;:::-;;;;;;;;;;;;;;27131:29;;;;;;37288:292;;;;;;:::i;:::-;;:::i;29286:285::-;;;:::i;37061:219::-;;;:::i;26942:36::-;;;;;27167:35;;;;;;33908:126;;;:::i;27028:27::-;;;;;;27719:38;;;;;;31566:617;;;;;;:::i;:::-;;:::i;27520:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;26125:201;;;;;;:::i;:::-;;:::i;30433:132::-;;;:::i;36528:525::-;;;:::i;29579:188::-;-1:-1:-1;;;;;29743:16:0;;29633:7;29743:16;;;:7;:16;;;;;;;;;29701:22;:31;;;;;;29736:4;;29682:16;:14;:16::i;:::-;:50;;;;:::i;:::-;-1:-1:-1;;;;;29660:18:0;;;;;;:9;:18;;;;;;:73;;;;:::i;:::-;:80;;;;:::i;:::-;:99;;;;:::i;:::-;29653:106;29579:188;-1:-1:-1;;29579:188:0:o;34700:1130::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;;;;;;;;;34780:12:::1;;34762:15;:30;34754:107;;;::::0;;-1:-1:-1;;;34754:107:0;;5732:2:1;34754:107:0::1;::::0;::::1;5714:21:1::0;5751:18;;;5744:30;;;;5810:34;5790:18;;;5783:62;5881:34;5861:18;;;5854:62;5933:19;;34754:107:0::1;5530:428:1::0;34754:107:0::1;34874:20;34905:27:::0;34949:12:::1;;34965:1;34949:17:::0;34945:516:::1;;34998:37;::::0;-1:-1:-1;;;34998:37:0;;35029:4:::1;34998:37;::::0;::::1;933:74:1::0;34998:12:0::1;-1:-1:-1::0;;;;;34998:22:0::1;::::0;::::1;::::0;906:18:1;;34998:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35062:12;::::0;34983:52;;-1:-1:-1;;;;;;35062:12:0::1;35054:35:::0;35050:199:::1;;35132:12;::::0;:37:::1;::::0;-1:-1:-1;;;35132:37:0;;35163:4:::1;35132:37;::::0;::::1;933:74:1::0;-1:-1:-1;;;;;35132:12:0;;::::1;::::0;:22:::1;::::0;906:18:1;;35132:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35110:59;;34945:516;;35050:199;-1:-1:-1::0;35232:1:0::1;34945:516;;;35281:17;35316:15;35301:12;;:30;;;;:::i;:::-;35281:50;;35374:9;35361:10;;:22;;;;:::i;:::-;35346:37;;35440:9;35420:17;;:29;;;;:::i;:::-;35398:51;;35266:195;34945:516;35488:15;35473:12;:30:::0;35518:16;;35514:97:::1;;35551:48;35577:7;25289:6:::0;;-1:-1:-1;;;;;25289:6:0;;25216:87;35577:7:::1;-1:-1:-1::0;;;;;35551:12:0::1;:25;::::0;35586:12;35551:25:::1;:48::i;:::-;35633:12;::::0;-1:-1:-1;;;;;35633:12:0::1;35625:35:::0;;::::1;::::0;:62:::1;;;35686:1;35664:19;:23;35625:62;35621:150;;;35704:55;35730:7;25289:6:::0;;-1:-1:-1;;;;;25289:6:0;;25216:87;35730:7:::1;35704:12;::::0;-1:-1:-1;;;;;35704:12:0::1;::::0;35739:19;35704:25:::1;:55::i;:::-;35788:34;::::0;552:25:1;;;35788:34:0::1;::::0;540:2:1;525:18;35788:34:0::1;;;;;;;;34743:1087;;34700:1130::o:0;30573:124::-;-1:-1:-1;;;;;30670:18:0;;30630:7;30670:18;;;:9;:18;;;;;;30657:32;;30661:7;;30657:3;:32::i;29775:118::-;29830:7;29870:15;;29857:10;;:28;;;;:::i;:::-;29850:35;;29775:118;:::o;33478:422::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;33539:10:::1;41724:16;:14;:16::i;:::-;41701:20;:39:::0;41781:23:::1;:21;:23::i;:::-;41751:27;:53:::0;41832:26:::1;:24;:26::i;:::-;41815:14;:43:::0;-1:-1:-1;;;;;41873:21:0;::::1;::::0;41869:303:::1;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1::0;;;;;41911:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;41994:20:::1;::::0;41960:22:::1;:31:::0;;;;;;:54;42055:22:::1;41919:7:::0;42055:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;42029:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;42133:27:::1;::::0;42092:29:::1;:38:::0;;;;;;:68;41869:303:::1;33574:12:::2;::::0;-1:-1:-1;;;;;33574:12:0::2;33566:35:::0;33562:331:::2;;33650:10;33618:14;33635:26:::0;;;:14:::2;:26;::::0;;;;;33680:10;;33676:206:::2;;33726:10;33740:1;33711:26:::0;;;:14:::2;:26;::::0;;;;:30;33760:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;33760:12:0;;::::2;::::0;33798:6;33760:25:::2;:45::i;:::-;33829:37;::::0;552:25:1;;;33847:10:0::2;::::0;33829:37:::2;::::0;540:2:1;525:18;33829:37:0::2;;;;;;;;33676:206;33603:290;33562:331;-1:-1:-1::0;18631:1:0;19585:7;:22;33478:422::o;36059:461::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;36130:12:::1;::::0;:17;:49;::::1;;;;36167:12;-1:-1:-1::0;;;;;36151:28:0::1;:12;-1:-1:-1::0;;;;;36151:28:0::1;;36130:49;36122:156;;;::::0;-1:-1:-1;;;36122:156:0;;6714:2:1;36122:156:0::1;::::0;::::1;6696:21:1::0;6753:2;6733:18;;;6726:30;6792:34;6772:18;;;6765:62;6863:34;6843:18;;;6836:62;6935:32;6914:19;;;6907:61;6985:19;;36122:156:0::1;6512:498:1::0;36122:156:0::1;36312:37;::::0;-1:-1:-1;;;36312:37:0;;36343:4:::1;36312:37;::::0;::::1;933:74:1::0;36289:20:0::1;::::0;36312:12:::1;-1:-1:-1::0;;;;;36312:22:0::1;::::0;::::1;::::0;906:18:1;;36312:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36289:60:::0;-1:-1:-1;36364:16:0;;36360:100:::1;;36397:51;-1:-1:-1::0;;;;;36397:12:0::1;:25;36423:10;36435:12:::0;36397:25:::1;:51::i;:::-;36475:37;::::0;552:25:1;;;36475:37:0::1;::::0;540:2:1;525:18;36475:37:0::1;;;;;;;;36111:409;36059:461::o:0;32191:115::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;32258:10:::1;41724:16;:14;:16::i;:::-;41701:20;:39:::0;41781:23:::1;:21;:23::i;:::-;41751:27;:53:::0;41832:26:::1;:24;:26::i;:::-;41815:14;:43:::0;-1:-1:-1;;;;;41873:21:0;::::1;::::0;41869:303:::1;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1::0;;;;;41911:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;41994:20:::1;::::0;41960:22:::1;:31:::0;;;;;;:54;42055:22:::1;41919:7:::0;42055:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;42029:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;42133:27:::1;::::0;42092:29:::1;:38:::0;;;;;;:68;41869:303:::1;32281:17:::2;32291:6;32281:9;:17::i;27578:28::-:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27578:28:0;:::o;30209:216::-;-1:-1:-1;;;;;30394:23:0;;30270:7;30394:23;;;:14;:23;;;;;;;;;30345:29;:38;;;;;;30387:4;;30319:23;:21;:23::i;33163:307::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;33217:10:::1;41724:16;:14;:16::i;:::-;41701:20;:39:::0;41781:23:::1;:21;:23::i;:::-;41751:27;:53:::0;41832:26:::1;:24;:26::i;:::-;41815:14;:43:::0;-1:-1:-1;;;;;41873:21:0;::::1;::::0;41869:303:::1;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1::0;;;;;41911:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;41994:20:::1;::::0;41960:22:::1;:31:::0;;;;;;:54;42055:22:::1;41919:7:::0;42055:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;42029:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;42133:27:::1;::::0;42092:29:::1;:38:::0;;;;;;:68;41869:303:::1;33265:10:::2;33240:14;33257:19:::0;;;:7:::2;:19;::::0;;;;;33291:10;;33287:176:::2;;33326:10;33340:1;33318:19:::0;;;:7:::2;:19;::::0;;;;:23;33356:45:::2;::::0;:12:::2;-1:-1:-1::0;;;;;33356:25:0::2;::::0;33394:6;33356:25:::2;:45::i;:::-;33421:30;::::0;552:25:1;;;33432:10:0::2;::::0;33421:30:::2;::::0;540:2:1;525:18;33421:30:0::2;406:177:1::0;38101:67:0;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;38150:10:::1;:8;:10::i;:::-;38101:67::o:0;32314:101::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;32390:17:::1;32400:6:::0;32390:9:::1;:17::i;29901:300::-:0;29955:7;29979:12;;29995:1;29979:17;29975:84;;-1:-1:-1;30020:27:0;;;29901:300::o;29975:84::-;30181:12;;30154:17;;30136:14;;30107:26;:24;:26::i;:::-;:43;;;;:::i;:::-;30106:65;;;;:::i;:::-;:72;;30174:4;30106:72;:::i;:::-;:87;;;;:::i;:::-;30076:27;;:117;;;;:::i;25867:103::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;25932:30:::1;25959:1;25932:18;:30::i;38202:179::-:0;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;38324:49:::1;38343:12;38357:15;38324:18;:49::i;:::-;38202:179:::0;;:::o;34098:421::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;34222:64:::1;-1:-1:-1::0;;;;;34222:12:0::1;:29;34252:10;34272:4;34279:6:::0;34222:29:::1;:64::i;:::-;34309:12;::::0;-1:-1:-1;;;;;34309:12:0::1;34301:35:::0;;::::1;::::0;:56:::1;;;34356:1;34340:13;:17;34301:56;34297:157;;;34374:68;34404:7;25289:6:::0;;-1:-1:-1;;;;;25289:6:0;;25216:87;34404:7:::1;34374:12;::::0;-1:-1:-1;;;;;34374:12:0::1;::::0;34421:4:::1;34428:13:::0;34374:29:::1;:68::i;:::-;34464:47;34479:6;34487:13;34502:8;34464:14;:47::i;:::-;34098:421:::0;;;:::o;29147:131::-;29204:7;29231:39;29240:15;29257:12;;29231:8;:39::i;38030:63::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;38077:8:::1;:6;:8::i;35838:213::-:0;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;35933:58:::1;-1:-1:-1::0;;;;;35933:33:0;::::1;35967:10;35979:11:::0;35933:33:::1;:58::i;:::-;36007:36;::::0;;-1:-1:-1;;;;;7207:55:1;;7189:74;;7294:2;7279:18;;7272:34;;;36007:36:0::1;::::0;7162:18:1;36007:36:0::1;7015:297:1::0;34527:165:0;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;27613:34:0;;;;;;;;;;;;37614:408;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;37725:12:::1;-1:-1:-1::0;;;;;37700:38:0::1;:13;-1:-1:-1::0;;;;;37700:38:0::1;::::0;37692:108:::1;;;::::0;-1:-1:-1;;;37692:108:0;;7519:2:1;37692:108:0::1;::::0;::::1;7501:21:1::0;7558:2;7538:18;;;7531:30;7597:34;7577:18;;;7570:62;7668:27;7648:18;;;7641:55;7713:19;;37692:108:0::1;7317:421:1::0;37692:108:0::1;37844:12;-1:-1:-1::0;;;;;37819:38:0::1;:13;-1:-1:-1::0;;;;;37819:38:0::1;::::0;37811:109:::1;;;::::0;-1:-1:-1;;;37811:109:0;;7945:2:1;37811:109:0::1;::::0;::::1;7927:21:1::0;7984:2;7964:18;;;7957:30;8023:34;8003:18;;;7996:62;8094:28;8074:18;;;8067:56;8140:19;;37811:109:0::1;7743:422:1::0;37811:109:0::1;37931:12;:36:::0;;-1:-1:-1;;37931:36:0::1;-1:-1:-1::0;;;;;37931:36:0;::::1;::::0;;::::1;::::0;;;37983:31:::1;::::0;933:74:1;;;37983:31:0::1;::::0;921:2:1;906:18;37983:31:0::1;773:240:1::0;30705:359:0;30782:7;;30802:236;30821:11;:18;30817:22;;30802:236;;;30909:11;30921:1;30909:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;30883:23:0;;;;:14;:23;;;;;;;;30865:41;;:15;:41;:::i;:::-;:58;30861:166;;;30993:18;;30970:17;30988:1;30970:20;;;;;;;;:::i;:::-;;;;;;;;;30951:16;:39;;;;:::i;:::-;:60;;;;:::i;:::-;30944:67;;;;;30861:166;30841:3;;;:::i;:::-;;;30802:236;;;-1:-1:-1;31055:1:0;;30705:359;-1:-1:-1;;;30705:359:0:o;31126:432::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;23033:7;;-1:-1:-1;;;23033:7:0;;;;23287:9:::1;23279:38;;;::::0;-1:-1:-1;;;23279:38:0;;8701:2:1;23279:38:0::1;::::0;::::1;8683:21:1::0;8740:2;8720:18;;;8713:30;-1:-1:-1;;;8759:18:1;;;8752:46;8815:18;;23279:38:0::1;8499:340:1::0;23279:38:0::1;31206:10:::2;41724:16;:14;:16::i;:::-;41701:20;:39:::0;41781:23:::2;:21;:23::i;:::-;41751:27;:53:::0;41832:26:::2;:24;:26::i;:::-;41815:14;:43:::0;-1:-1:-1;;;;;41873:21:0;::::2;::::0;41869:303:::2;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1::0;;;;;41911:16:0;::::2;;::::0;;;:7:::2;:16;::::0;;;;;;;:34;;;;41994:20:::2;::::0;41960:22:::2;:31:::0;;;;;;:54;42055:22:::2;41919:7:::0;42055:13:::2;:22::i;:::-;-1:-1:-1::0;;;;;42029:23:0;::::2;;::::0;;;:14:::2;:23;::::0;;;;;;;:48;;;;42133:27:::2;::::0;42092:29:::2;:38:::0;;;;;;:68;41869:303:::2;31246:1:::3;31237:6;:10;31229:37;;;::::0;-1:-1:-1;;;31229:37:0;;9046:2:1;31229:37:0::3;::::0;::::3;9028:21:1::0;9085:2;9065:18;;;9058:30;9124:16;9104:18;;;9097:44;9158:18;;31229:37:0::3;8844:338:1::0;31229:37:0::3;31307:6;31292:12;;:21;;;;:::i;:::-;31277:12;:36:::0;31358:10:::3;31348:21;::::0;;;:9:::3;:21;::::0;;;;;:30:::3;::::0;31372:6;;31348:30:::3;:::i;:::-;31334:10;31324:21;::::0;;;:9:::3;:21;::::0;;;;;;;:54;;;;31389:14:::3;:26:::0;;;;;;31418:15:::3;31389:44:::0;;31444:64:::3;::::0;:12:::3;-1:-1:-1::0;;;;;31444:29:0::3;::::0;31494:4:::3;31501:6:::0;31444:29:::3;:64::i;:::-;31524:26;::::0;552:25:1;;;31531:10:0::3;::::0;31524:26:::3;::::0;540:2:1;525:18;31524:26:0::3;406:177:1::0;37288:292:0;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;37404:12:::1;;37386:15;:30;37364:168;;;::::0;-1:-1:-1;;;37364:168:0;;9389:2:1;37364:168:0::1;::::0;::::1;9371:21:1::0;9428:2;9408:18;;;9401:30;9467:34;9447:18;;;9440:62;9538:34;9518:18;;;9511:62;9610:26;9589:19;;;9582:55;9654:19;;37364:168:0::1;9187:492:1::0;37364:168:0::1;37543:29;37563:8;37543:19;:29::i;:::-;37288:292:::0;:::o;29286:285::-;29333:7;29357:12;;29373:1;29357:17;29353:77;;-1:-1:-1;29398:20:0;;;29286:285::o;29353:77::-;29551:12;;29531:10;;29513:14;;29484:26;:24;:26::i;:::-;:43;;;;:::i;:::-;29483:58;;;;:::i;:::-;:65;;29544:4;29483:65;:::i;:::-;:80;;;;:::i;:::-;29460:20;;:103;;;;:::i;37061:219::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;37137:9:::1;::::0;;37114:20:::1;37157:13:::0;;;37181:48:::1;37207:7;25289:6:::0;;-1:-1:-1;;;;;25289:6:0;;25216:87;37207:7:::1;-1:-1:-1::0;;;;;37181:12:0::1;:25;::::0;37216:12;37181:25:::1;:48::i;:::-;37245:27;::::0;552:25:1;;;37245:27:0::1;::::0;540:2:1;525:18;37245:27:0::1;406:177:1::0;33908:126:0;33963:10;33953:21;;;;:9;:21;;;;;;33944:31;;:8;:31::i;:::-;33986:11;:9;:11::i;:::-;34008:18;:16;:18::i;31566:617::-;18675:1;19273:7;;:19;19265:63;;;;-1:-1:-1;;;19265:63:0;;6354:2:1;19265:63:0;;;6336:21:1;6393:2;6373:18;;;6366:30;6432:33;6412:18;;;6405:61;6483:18;;19265:63:0;6152:355:1;19265:63:0;18675:1;19406:7;:18;23033:7;;-1:-1:-1;;;23033:7:0;;;;23287:9:::1;23279:38;;;::::0;-1:-1:-1;;;23279:38:0;;8701:2:1;23279:38:0::1;::::0;::::1;8683:21:1::0;8740:2;8720:18;;;8713:30;-1:-1:-1;;;8759:18:1;;;8752:46;8815:18;;23279:38:0::1;8499:340:1::0;23279:38:0::1;31702:10:::2;41724:16;:14;:16::i;:::-;41701:20;:39:::0;41781:23:::2;:21;:23::i;:::-;41751:27;:53:::0;41832:26:::2;:24;:26::i;:::-;41815:14;:43:::0;-1:-1:-1;;;;;41873:21:0;::::2;::::0;41869:303:::2;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1::0;;;;;41911:16:0;::::2;;::::0;;;:7:::2;:16;::::0;;;;;;;:34;;;;41994:20:::2;::::0;41960:22:::2;:31:::0;;;;;;:54;42055:22:::2;41919:7:::0;42055:13:::2;:22::i;:::-;-1:-1:-1::0;;;;;42029:23:0;::::2;;::::0;;;:14:::2;:23;::::0;;;;;;;:48;;;;42133:27:::2;::::0;42092:29:::2;:38:::0;;;;;;:68;41869:303:::2;31742:1:::3;31733:6;:10;31725:37;;;::::0;-1:-1:-1;;;31725:37:0;;9046:2:1;31725:37:0::3;::::0;::::3;9028:21:1::0;9085:2;9065:18;;;9058:30;9124:16;9104:18;;;9097:44;9158:18;;31725:37:0::3;8844:338:1::0;31725:37:0::3;31803:6;31788:12;;:21;;;;:::i;:::-;31773:12;:36:::0;31854:10:::3;31844:21;::::0;;;:9:::3;:21;::::0;;;;;:30:::3;::::0;31868:6;;31844:30:::3;:::i;:::-;31830:10;31820:21;::::0;;;:9:::3;:21;::::0;;;;;;:54;;;;31906:93;;;;;::::3;::::0;::::3;10056:34:1::0;;;;31966:4:0::3;10106:18:1::0;;;10099:43;10158:18;;;10151:34;;;10201:18;;;10194:34;;;10277:4;10265:17;;10244:19;;;10237:46;10299:19;;;10292:35;;;10343:19;;;10336:35;;;-1:-1:-1;;;;;31924:12:0::3;31906:39;::::0;::::3;::::0;9967:19:1;;31906:93:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;32027:10:0::3;32012:26;::::0;;;:14:::3;:26;::::0;;;;32041:15:::3;32012:44:::0;;32069:64:::3;::::0;-1:-1:-1;32069:12:0::3;-1:-1:-1::0;;;;;32069:29:0::3;::::0;-1:-1:-1;32119:4:0::3;32126:6:::0;32069:29:::3;:64::i;:::-;32149:26;::::0;552:25:1;;;32156:10:0::3;::::0;32149:26:::3;::::0;540:2:1;525:18;32149:26:0::3;;;;;;;-1:-1:-1::0;;18631:1:0;19585:7;:22;-1:-1:-1;;;;31566:617:0:o;26125:201::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;-1:-1:-1;;;;;26214:22:0;::::1;26206:73;;;::::0;-1:-1:-1;;;26206:73:0;;10584:2:1;26206:73:0::1;::::0;::::1;10566:21:1::0;10623:2;10603:18;;;10596:30;10662:34;10642:18;;;10635:62;10733:8;10713:18;;;10706:36;10759:19;;26206:73:0::1;10382:402:1::0;26206:73:0::1;26290:28;26309:8;26290:18;:28::i;30433:132::-:0;30495:7;30542:15;;30522:17;;:35;;;;:::i;36528:525::-;25289:6;;-1:-1:-1;;;;;25289:6:0;21690:10;25436:23;25428:68;;;;-1:-1:-1;;;25428:68:0;;5371:2:1;25428:68:0;;;5353:21:1;;;5390:18;;;5383:30;-1:-1:-1;;;;;;;;;;;5429:18:1;;;5422:62;5501:18;;25428:68:0;5169:356:1;25428:68:0;36608:12:::1;::::0;-1:-1:-1;;;;;36608:12:0::1;36592:113;;;::::0;-1:-1:-1;;;36592:113:0;;10991:2:1;36592:113:0::1;::::0;::::1;10973:21:1::0;11030:2;11010:18;;;11003:30;11069:34;11049:18;;;11042:62;11140:34;11120:18;;;11113:62;11212:3;11191:19;;;11184:32;11233:19;;36592:113:0::1;10789:469:1::0;36592:113:0::1;36724:12;::::0;:17;36716:94:::1;;;::::0;;-1:-1:-1;;;36716:94:0;;11465:2:1;36716:94:0::1;::::0;::::1;11447:21:1::0;11484:18;;;11477:30;;;;11543:34;11523:18;;;11516:62;11614:34;11594:18;;;11587:62;11666:19;;36716:94:0::1;11263:428:1::0;36716:94:0::1;36844:12;::::0;:37:::1;::::0;-1:-1:-1;;;36844:37:0;;36875:4:::1;36844:37;::::0;::::1;933:74:1::0;36821:20:0::1;::::0;-1:-1:-1;;;;;36844:12:0::1;::::0;:22:::1;::::0;906:18:1;;36844:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36821:60:::0;-1:-1:-1;36896:16:0;;36892:100:::1;;36929:12;::::0;:51:::1;::::0;-1:-1:-1;;;;;36929:12:0::1;36955:10;36967:12:::0;36929:25:::1;:51::i;:::-;37007:38;::::0;552:25:1;;;37007:38:0::1;::::0;540:2:1;525:18;37007:38:0::1;406:177:1::0;13561:211:0;13705:58;;-1:-1:-1;;;;;7207:55:1;;13705:58:0;;;7189:74:1;7279:18;;;7272:34;;;13678:86:0;;13698:5;;13728:23;;7162:18:1;;13705:58:0;;;;-1:-1:-1;;13705:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;13678:19;:86::i;32423:732::-;32494:1;32485:6;:10;32477:40;;;;-1:-1:-1;;;32477:40:0;;11898:2:1;32477:40:0;;;11880:21:1;11937:2;11917:18;;;11910:30;11976:19;11956:18;;;11949:47;12013:18;;32477:40:0;11696:341:1;32477:40:0;32556:10;32528:15;32546:21;;;:9;:21;;;;;;32586:17;;;;32578:71;;;;-1:-1:-1;;;32578:71:0;;12244:2:1;32578:71:0;;;12226:21:1;12283:2;12263:18;;;12256:30;12322:34;12302:18;;;12295:62;12393:11;12373:18;;;12366:39;12422:19;;32578:71:0;12042:405:1;32578:71:0;32690:6;32675:12;;:21;;;;:::i;:::-;32660:12;:36;32707:20;32730:23;32734:10;32746:6;32730:3;:23::i;:::-;32707:46;-1:-1:-1;32788:16:0;32798:6;32788:7;:16;:::i;:::-;32774:10;32764:21;;;;:9;:21;;;;;:40;;;;32845:21;32854:12;32845:6;:21;:::i;:::-;32815:51;-1:-1:-1;32877:58:0;-1:-1:-1;;;;;32877:12:0;:25;32903:10;32815:51;32877:25;:58::i;:::-;32951:42;;552:25:1;;;32961:10:0;;32951:42;;540:2:1;525:18;32951:42:0;;;;;;;33008:16;;33004:144;;33046:39;;552:25:1;;;33060:10:0;;33046:39;;540:2:1;525:18;33046:39:0;;;;;;;33124:12;33112:9;;:24;;;;:::i;:::-;33100:9;:36;33004:144;32466:689;;;32423:732;:::o;24021:120::-;23033:7;;-1:-1:-1;;;23033:7:0;;;;23557:41;;;;-1:-1:-1;;;23557:41:0;;12654:2:1;23557:41:0;;;12636:21:1;12693:2;12673:18;;;12666:30;12732:22;12712:18;;;12705:50;12772:18;;23557:41:0;12452:344:1;23557:41:0;24080:7:::1;:15:::0;;-1:-1:-1;;;;24080:15:0::1;::::0;;24111:22:::1;21690:10:::0;24120:12:::1;24111:22;::::0;-1:-1:-1;;;;;951:55:1;;;933:74;;921:2;906:18;24111:22:0::1;;;;;;;24021:120::o:0;26486:191::-;26579:6;;;-1:-1:-1;;;;;26596:17:0;;;-1:-1:-1;;26596:17:0;;;;;;;26629:40;;26579:6;;;26596:17;26579:6;;26629:40;;26560:16;;26629:40;26549:128;26486:191;:::o;38580:1010::-;38726:18;:25;38703:12;:19;:48;38695:125;;;;;-1:-1:-1;;;38695:125:0;;13003:2:1;38695:125:0;;;12985:21:1;13022:18;;;13015:30;;;;13081:34;13061:18;;;13054:62;13152:34;13132:18;;;13125:62;13204:19;;38695:125:0;12801:428:1;38695:125:0;38862:2;38839:12;:19;:25;;38831:111;;;;-1:-1:-1;;;38831:111:0;;13436:2:1;38831:111:0;;;13418:21:1;13475:2;13455:18;;;13448:30;13514:34;13494:18;;;13487:62;13585:34;13565:18;;;13558:62;13657:11;13636:19;;;13629:40;13686:19;;38831:111:0;13234:477:1;38831:111:0;38953:23;38991:25;39019:16;;39038:1;39019:20;;;;:::i;:::-;38991:48;;39054:9;39050:380;39073:12;:19;39069:1;:23;39050:380;;;39139:15;39121:12;39134:1;39121:15;;;;;;;;:::i;:::-;;;;;;;:33;39113:77;;;;-1:-1:-1;;;39113:77:0;;13918:2:1;39113:77:0;;;13900:21:1;13957:2;13937:18;;;13930:30;13996:33;13976:18;;;13969:61;14047:18;;39113:77:0;13716:355:1;39113:77:0;39236:17;39212:18;39231:1;39212:21;;;;;;;;:::i;:::-;;;;;;;:41;39204:112;;;;-1:-1:-1;;;39204:112:0;;14278:2:1;39204:112:0;;;14260:21:1;14317:2;14297:18;;;14290:30;14356:34;14336:18;;;14329:62;14427:28;14407:18;;;14400:56;14473:19;;39204:112:0;14076:422:1;39204:112:0;39348:12;39361:1;39348:15;;;;;;;;:::i;:::-;;;;;;;39330:33;;39397:18;39416:1;39397:21;;;;;;;;:::i;:::-;;;;;;;39377:41;;39094:3;;;;:::i;:::-;;;39050:380;;;-1:-1:-1;39440:26:0;;;;:11;;:26;;;;;:::i;:::-;-1:-1:-1;39477:38:0;;;;:17;;:38;;;;;:::i;:::-;;39531:51;39549:12;39563:18;39531:51;;;;;;;:::i;:::-;;;;;;;;38684:906;;38580:1010;;:::o;13780:248::-;13951:68;;-1:-1:-1;;;;;15694:15:1;;;13951:68:0;;;15676:34:1;15746:15;;15726:18;;;15719:43;15778:18;;;15771:34;;;13924:96:0;;13944:5;;13974:27;;15588:18:1;;13951:68:0;15413:398:1;39644:1954:0;39754:1;41724:16;:14;:16::i;:::-;41701:20;:39;41781:23;:21;:23::i;:::-;41751:27;:53;41832:26;:24;:26::i;:::-;41815:14;:43;-1:-1:-1;;;;;41873:21:0;;;41869:303;;41930:15;41937:7;41930:6;:15::i;:::-;-1:-1:-1;;;;;41911:16:0;;;;;;:7;:16;;;;;;;;:34;;;;41994:20;;41960:22;:31;;;;;;:54;42055:22;41919:7;42055:13;:22::i;:::-;-1:-1:-1;;;;;42029:23:0;;;;;;:14;:23;;;;;;;;:48;;;;42133:27;;42092:29;:38;;;;;;:68;41869:303;39773:12;;39769:74:::1;;39802:29;39822:8;39802:19;:29::i;:::-;39878:12;;39859:15;:31;39855:527;;39929:15;::::0;39920:24:::1;::::0;:6;:24:::1;:::i;:::-;39907:10;:37:::0;39995:15:::1;::::0;39979:31:::1;::::0;:13;:31:::1;:::i;:::-;39959:17;:51:::0;39855:527:::1;;;40043:17;40078:15;40063:12;;:30;;;;:::i;:::-;40043:50;;40108:16;40139:10;;40127:9;:22;;;;:::i;:::-;40199:15;::::0;40108:41;;-1:-1:-1;40178:17:0::1;40108:41:::0;40178:6;:17:::1;:::i;:::-;40177:37;;;;:::i;:::-;40164:10;:50:::0;40267:17:::1;::::0;40229:23:::1;::::0;40255:29:::1;::::0;:9;:29:::1;:::i;:::-;40355:15;::::0;40229:55;;-1:-1:-1;40320:31:0::1;40229:55:::0;40320:13;:31:::1;:::i;:::-;40319:51;;;;:::i;:::-;40299:17;:71:::0;-1:-1:-1;;;39855:527:0::1;40757:37;::::0;-1:-1:-1;;;40757:37:0;;40788:4:::1;40757:37;::::0;::::1;933:74:1::0;40742:12:0::1;::::0;40757::::1;-1:-1:-1::0;;;;;40757:22:0::1;::::0;::::1;::::0;906:18:1;;40757:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40742:52;;40825:12;-1:-1:-1::0;;;;;40809:28:0::1;:12;-1:-1:-1::0;;;;;40809:28:0::1;;40805:357;;40886:15;::::0;40876:25:::1;::::0;:7;:25:::1;:::i;:::-;40862:10;;:39;;40854:76;;;::::0;-1:-1:-1;;;40854:76:0;;16018:2:1;40854:76:0::1;::::0;::::1;16000:21:1::0;16057:2;16037:18;;;16030:30;16096:26;16076:18;;;16069:54;16140:18;;40854:76:0::1;15816:348:1::0;40854:76:0::1;40805:357;;;41106:15;::::0;41090:12:::1;::::0;41080:22:::1;::::0;:7;:22:::1;:::i;:::-;41079:42;;;;:::i;:::-;41065:10;;:56;;41057:93;;;::::0;-1:-1:-1;;;41057:93:0;;16018:2:1;41057:93:0::1;::::0;::::1;16000:21:1::0;16057:2;16037:18;;;16030:30;16096:26;16076:18;;;16069:54;16140:18;;41057:93:0::1;15816:348:1::0;41057:93:0::1;41186:12;::::0;-1:-1:-1;;;;;41186:12:0::1;41178:35:::0;41174:240:::1;;41252:12;::::0;:37:::1;::::0;-1:-1:-1;;;41252:37:0;;41283:4:::1;41252:37;::::0;::::1;933:74:1::0;41230:19:0::1;::::0;-1:-1:-1;;;;;41252:12:0::1;::::0;:22:::1;::::0;906:18:1;;41252:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41230:59;;41350:15;;41333:14;:32;;;;:::i;:::-;41312:17;;:53;;41304:98;;;::::0;-1:-1:-1;;;41304:98:0;;16371:2:1;41304:98:0::1;::::0;::::1;16353:21:1::0;;;16390:18;;;16383:30;16449:34;16429:18;;;16422:62;16501:18;;41304:98:0::1;16169:356:1::0;41304:98:0::1;41215:199;41174:240;41443:15;41426:14;:32:::0;;;41502:15:::1;::::0;41484:33:::1;::::0;::::1;:::i;:::-;41469:12;:48:::0;41535:55:::1;::::0;;16732:25:1;;;16788:2;16773:18;;16766:34;;;16816:18;;;16809:34;;;41535:55:0::1;::::0;16720:2:1;16705:18;41535:55:0::1;;;;;;;39758:1840;39644:1954:::0;;;;:::o;20133:106::-;20191:7;20222:1;20218;:5;:13;;20230:1;20218:13;;;20226:1;20218:13;20211:20;20133:106;-1:-1:-1;;;20133:106:0:o;23762:118::-;23033:7;;-1:-1:-1;;;23033:7:0;;;;23287:9;23279:38;;;;-1:-1:-1;;;23279:38:0;;8701:2:1;23279:38:0;;;8683:21:1;8740:2;8720:18;;;8713:30;-1:-1:-1;;;8759:18:1;;;8752:46;8815:18;;23279:38:0;8499:340:1;23279:38:0;23832:4:::1;23822:14:::0;;-1:-1:-1;;;;23822:14:0::1;-1:-1:-1::0;;;23822:14:0::1;::::0;;23852:20:::1;23859:12;21690:10:::0;;21610:98;38417:155;38483:15;:26;;;38525:39;;552:25:1;;;38525:39:0;;540:2:1;525:18;38525:39:0;406:177:1;16134:716:0;16558:23;16584:69;16612:4;16584:69;;;;;;;;;;;;;;;;;16592:5;-1:-1:-1;;;;;16584:27:0;;;:69;;;;;:::i;:::-;16668:17;;16558:95;;-1:-1:-1;16668:21:0;16664:179;;16765:10;16754:30;;;;;;;;;;;;:::i;:::-;16746:85;;;;-1:-1:-1;;;16746:85:0;;17338:2:1;16746:85:0;;;17320:21:1;17377:2;17357:18;;;17350:30;17416:34;17396:18;;;17389:62;17487:12;17467:18;;;17460:40;17517:19;;16746:85:0;17136:406:1;5448:229:0;5585:12;5617:52;5639:6;5647:4;5653:1;5656:12;5617:21;:52::i;:::-;5610:59;5448:229;-1:-1:-1;;;;5448:229:0:o;6568:510::-;6738:12;6796:5;6771:21;:30;;6763:81;;;;-1:-1:-1;;;6763:81:0;;17749:2:1;6763:81:0;;;17731:21:1;17788:2;17768:18;;;17761:30;17827:34;17807:18;;;17800:62;17898:8;17878:18;;;17871:36;17924:19;;6763:81:0;17547:402:1;6763:81:0;-1:-1:-1;;;;;2998:19:0;;;6855:60;;;;-1:-1:-1;;;6855:60:0;;18156:2:1;6855:60:0;;;18138:21:1;18195:2;18175:18;;;18168:30;18234:31;18214:18;;;18207:59;18283:18;;6855:60:0;17954:353:1;6855:60:0;6929:12;6943:23;6970:6;-1:-1:-1;;;;;6970:11:0;6989:5;6996:4;6970:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6928:73;;;;7019:51;7036:7;7045:10;7057:12;7019:16;:51::i;:::-;7012:58;6568:510;-1:-1:-1;;;;;;;6568:510:0:o;9254:712::-;9404:12;9433:7;9429:530;;;-1:-1:-1;9464:10:0;9457:17;;9429:530;9578:17;;:21;9574:374;;9776:10;9770:17;9837:15;9824:10;9820:2;9816:19;9809:44;9574:374;9919:12;9912:20;;-1:-1:-1;;;9912:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:196:1;82:20;;-1:-1:-1;;;;;131:54:1;;121:65;;111:93;;200:1;197;190:12;111:93;14:196;;;:::o;215:186::-;274:6;327:2;315:9;306:7;302:23;298:32;295:52;;;343:1;340;333:12;295:52;366:29;385:9;366:29;:::i;588:180::-;647:6;700:2;688:9;679:7;675:23;671:32;668:52;;;716:1;713;706:12;668:52;-1:-1:-1;739:23:1;;588:180;-1:-1:-1;588:180:1:o;1210:184::-;-1:-1:-1;;;1259:1:1;1252:88;1359:4;1356:1;1349:15;1383:4;1380:1;1373:15;1399:902;1453:5;1506:3;1499:4;1491:6;1487:17;1483:27;1473:55;;1524:1;1521;1514:12;1473:55;1560:6;1547:20;1586:4;1609:18;1646:2;1642;1639:10;1636:36;;;1652:18;;:::i;:::-;1698:2;1695:1;1691:10;1730:2;1724:9;1793:2;1789:7;1784:2;1780;1776:11;1772:25;1764:6;1760:38;1848:6;1836:10;1833:22;1828:2;1816:10;1813:18;1810:46;1807:72;;;1859:18;;:::i;:::-;1895:2;1888:22;1945:18;;;2021:15;;;2017:24;;;1979:15;;;;-1:-1:-1;2053:15:1;;;2050:35;;;2081:1;2078;2071:12;2050:35;2117:2;2109:6;2105:15;2094:26;;2129:142;2145:6;2140:3;2137:15;2129:142;;;2211:17;;2199:30;;2249:12;;;;2162;;;;2129:142;;2306:595;2424:6;2432;2485:2;2473:9;2464:7;2460:23;2456:32;2453:52;;;2501:1;2498;2491:12;2453:52;2541:9;2528:23;2570:18;2611:2;2603:6;2600:14;2597:34;;;2627:1;2624;2617:12;2597:34;2650:61;2703:7;2694:6;2683:9;2679:22;2650:61;:::i;:::-;2640:71;;2764:2;2753:9;2749:18;2736:32;2720:48;;2793:2;2783:8;2780:16;2777:36;;;2809:1;2806;2799:12;2777:36;;2832:63;2887:7;2876:8;2865:9;2861:24;2832:63;:::i;:::-;2822:73;;;2306:595;;;;;:::o;2906:316::-;2983:6;2991;2999;3052:2;3040:9;3031:7;3027:23;3023:32;3020:52;;;3068:1;3065;3058:12;3020:52;-1:-1:-1;;3091:23:1;;;3161:2;3146:18;;3133:32;;-1:-1:-1;3212:2:1;3197:18;;;3184:32;;2906:316;-1:-1:-1;2906:316:1:o;3227:254::-;3295:6;3303;3356:2;3344:9;3335:7;3331:23;3327:32;3324:52;;;3372:1;3369;3362:12;3324:52;3395:29;3414:9;3395:29;:::i;:::-;3385:39;3471:2;3456:18;;;;3443:32;;-1:-1:-1;;;3227:254:1:o;3717:543::-;3810:6;3818;3826;3834;3842;3895:3;3883:9;3874:7;3870:23;3866:33;3863:53;;;3912:1;3909;3902:12;3863:53;3948:9;3935:23;3925:33;;4005:2;3994:9;3990:18;3977:32;3967:42;;4059:2;4048:9;4044:18;4031:32;4103:4;4096:5;4092:16;4085:5;4082:27;4072:55;;4123:1;4120;4113:12;4072:55;3717:543;;;;-1:-1:-1;4146:5:1;;4198:2;4183:18;;4170:32;;-1:-1:-1;4249:3:1;4234:19;4221:33;;3717:543;-1:-1:-1;;3717:543:1:o;4265:184::-;-1:-1:-1;;;4314:1:1;4307:88;4414:4;4411:1;4404:15;4438:4;4435:1;4428:15;4454:125;4494:4;4522:1;4519;4516:8;4513:34;;;4527:18;;:::i;:::-;-1:-1:-1;4564:9:1;;4454:125::o;4584:168::-;4624:7;4690:1;4686;4682:6;4678:14;4675:1;4672:21;4667:1;4660:9;4653:17;4649:45;4646:71;;;4697:18;;:::i;:::-;-1:-1:-1;4737:9:1;;4584:168::o;4757:274::-;4797:1;4823;4813:189;;-1:-1:-1;;;4855:1:1;4848:88;4959:4;4956:1;4949:15;4987:4;4984:1;4977:15;4813:189;-1:-1:-1;5016:9:1;;4757:274::o;5036:128::-;5076:3;5107:1;5103:6;5100:1;5097:13;5094:39;;;5113:18;;:::i;:::-;-1:-1:-1;5149:9:1;;5036:128::o;5963:184::-;6033:6;6086:2;6074:9;6065:7;6061:23;6057:32;6054:52;;;6102:1;6099;6092:12;6054:52;-1:-1:-1;6125:16:1;;5963:184;-1:-1:-1;5963:184:1:o;8170:::-;-1:-1:-1;;;8219:1:1;8212:88;8319:4;8316:1;8309:15;8343:4;8340:1;8333:15;8359:135;8398:3;8419:17;;;8416:43;;8439:18;;:::i;:::-;-1:-1:-1;8486:1:1;8475:13;;8359:135::o;14503:435::-;14556:3;14594:5;14588:12;14621:6;14616:3;14609:19;14647:4;14676:2;14671:3;14667:12;14660:19;;14713:2;14706:5;14702:14;14734:1;14744:169;14758:6;14755:1;14752:13;14744:169;;;14819:13;;14807:26;;14853:12;;;;14888:15;;;;14780:1;14773:9;14744:169;;;-1:-1:-1;14929:3:1;;14503:435;-1:-1:-1;;;;;14503:435:1:o;14943:465::-;15200:2;15189:9;15182:21;15163:4;15226:56;15278:2;15267:9;15263:18;15255:6;15226:56;:::i;:::-;15330:9;15322:6;15318:22;15313:2;15302:9;15298:18;15291:50;15358:44;15395:6;15387;15358:44;:::i;:::-;15350:52;14943:465;-1:-1:-1;;;;;14943:465:1:o;16854:277::-;16921:6;16974:2;16962:9;16953:7;16949:23;16945:32;16942:52;;;16990:1;16987;16980:12;16942:52;17022:9;17016:16;17075:5;17068:13;17061:21;17054:5;17051:32;17041:60;;17097:1;17094;17087:12;18312:258;18384:1;18394:113;18408:6;18405:1;18402:13;18394:113;;;18484:11;;;18478:18;18465:11;;;18458:39;18430:2;18423:10;18394:113;;;18525:6;18522:1;18519:13;18516:48;;;-1:-1:-1;;18560:1:1;18542:16;;18535:27;18312:258::o;18575:274::-;18704:3;18742:6;18736:13;18758:53;18804:6;18799:3;18792:4;18784:6;18780:17;18758:53;:::i;:::-;18827:16;;;;;18575:274;-1:-1:-1;;18575:274:1:o;18854:383::-;19003:2;18992:9;18985:21;18966:4;19035:6;19029:13;19078:6;19073:2;19062:9;19058:18;19051:34;19094:66;19153:6;19148:2;19137:9;19133:18;19128:2;19120:6;19116:15;19094:66;:::i;:::-;19221:2;19200:15;-1:-1:-1;;19196:29:1;19181:45;;;;19228:2;19177:54;;18854:383;-1:-1:-1;;18854:383:1:o
Swarm Source
ipfs://f1782956c14f05a3ad891819b987778508dbc25a816f61f86c1be51a059aafaa
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.