Address Details
contract
0x863a6AB90353e0d5636E12f9258e6aE6DB2766AB
- Contract Name
- StakingRewards
- Creator
- 0x136197–2f3145 at 0xf28b4c–770d88
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- Fetching transactions...
- Transfers
- Fetching transfers...
- Gas Used
- Fetching gas used...
- Last Balance Update
- 8321057
Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- StakingRewards
- Optimization enabled
- false
- Compiler version
- v0.8.3+commit.8d00100c
- EVM Version
- istanbul
- Verified at
- 2021-08-17T06:21:29.816635Z
Contract source code
// SPDX-License-Identifier: MIT // solhint-disable not-rely-on-time pragma solidity ^0.8.3; import "../../openzeppelin-solidity/contracts/Math.sol"; import "../../openzeppelin-solidity/contracts/SafeMath.sol"; import "../../openzeppelin-solidity/contracts/SafeERC20.sol"; import "../../openzeppelin-solidity/contracts/ReentrancyGuard.sol"; // Inheritance import "./IStakingRewards.sol"; import "./RewardsDistributionRecipient.sol"; // https://docs.synthetix.io/contracts/source/contracts/stakingrewards // XXX: removed Pausable contract StakingRewards is IStakingRewards, RewardsDistributionRecipient, ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for IERC20; /* ========== STATE VARIABLES ========== */ IERC20 public rewardsToken; IERC20 public stakingToken; uint256 public periodFinish = 0; uint256 public rewardRate = 0; uint256 public rewardsDuration = 7 days; uint256 public lastUpdateTime; uint256 public rewardPerTokenStored; mapping(address => uint256) public userRewardPerTokenPaid; mapping(address => uint256) public rewards; uint256 private _totalSupply; mapping(address => uint256) private _balances; /* ========== CONSTRUCTOR ========== */ constructor( address _owner, address _rewardsDistribution, address _rewardsToken, address _stakingToken ) Owned(_owner) { rewardsToken = IERC20(_rewardsToken); stakingToken = IERC20(_stakingToken); rewardsDistribution = _rewardsDistribution; } /* ========== VIEWS ========== */ function totalSupply() external view override returns (uint256) { return _totalSupply; } function balanceOf(address account) external view override returns (uint256) { return _balances[account]; } function lastTimeRewardApplicable() public view override returns (uint256) { return Math.min(block.timestamp, periodFinish); } function rewardPerToken() public view override returns (uint256) { if (_totalSupply == 0) { return rewardPerTokenStored; } return rewardPerTokenStored.add( lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply) ); } function earned(address account) public view override returns (uint256) { return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]); } function getRewardForDuration() external view override returns (uint256) { return rewardRate.mul(rewardsDuration); } /* ========== MUTATIVE FUNCTIONS ========== */ // XXX: removed notPaused function stake(uint256 amount) external override nonReentrant updateReward(msg.sender) { require(amount > 0, "Cannot stake 0"); _totalSupply = _totalSupply.add(amount); _balances[msg.sender] = _balances[msg.sender].add(amount); stakingToken.safeTransferFrom(msg.sender, address(this), amount); emit Staked(msg.sender, amount); } function withdraw(uint256 amount) public override nonReentrant updateReward(msg.sender) { require(amount > 0, "Cannot withdraw 0"); _totalSupply = _totalSupply.sub(amount); _balances[msg.sender] = _balances[msg.sender].sub(amount); stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount); } function getReward() public override 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 exit() external override { withdraw(_balances[msg.sender]); getReward(); } /* ========== RESTRICTED FUNCTIONS ========== */ function notifyRewardAmount(uint256 reward) external override onlyRewardsDistribution updateReward(address(0)) { if (block.timestamp >= periodFinish) { rewardRate = reward.div(rewardsDuration); } else { uint256 remaining = periodFinish.sub(block.timestamp); uint256 leftover = remaining.mul(rewardRate); rewardRate = reward.add(leftover).div(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)); require(rewardRate <= balance.div(rewardsDuration), "Provided reward too high"); lastUpdateTime = block.timestamp; periodFinish = block.timestamp.add(rewardsDuration); emit RewardAdded(reward); } // End rewards emission earlier function updatePeriodFinish(uint timestamp) external onlyOwner updateReward(address(0)) { periodFinish = timestamp; } // Added to support recovering LP Rewards from other systems such as BAL to be distributed to holders function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner { require(tokenAddress != address(stakingToken), "Cannot withdraw the staking token"); IERC20(tokenAddress).safeTransfer(owner, tokenAmount); emit Recovered(tokenAddress, tokenAmount); } function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner { require( block.timestamp > periodFinish, "Previous rewards period must be complete before changing the duration for the new period" ); rewardsDuration = _rewardsDuration; emit RewardsDurationUpdated(rewardsDuration); } /* ========== MODIFIERS ========== */ modifier updateReward(address account) { rewardPerTokenStored = rewardPerToken(); lastUpdateTime = lastTimeRewardApplicable(); if (account != address(0)) { rewards[account] = earned(account); userRewardPerTokenPaid[account] = rewardPerTokenStored; } _; } /* ========== EVENTS ========== */ event RewardAdded(uint256 reward); event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event RewardsDurationUpdated(uint256 newDuration); event Recovered(address token, uint256 amount); }
IStakingRewards.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24; // https://docs.synthetix.io/contracts/source/interfaces/istakingrewards interface IStakingRewards { // Views function lastTimeRewardApplicable() external view returns (uint256); function rewardPerToken() external view returns (uint256); function earned(address account) external view returns (uint256); function getRewardForDuration() external view returns (uint256); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); // Mutative function stake(uint256 amount) external; function withdraw(uint256 amount) external; function getReward() external; function exit() external; }
Owned.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; // https://docs.synthetix.io/contracts/source/contracts/owned contract Owned { address public owner; address public nominatedOwner; constructor(address _owner) { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { _onlyOwner(); _; } function _onlyOwner() private view { require(msg.sender == owner, "Only the contract owner may perform this action"); } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); }
RewardsDistributionRecipient.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; // Inheritance import "./Owned.sol"; // https://docs.synthetix.io/contracts/source/contracts/rewardsdistributionrecipient abstract contract RewardsDistributionRecipient is Owned { address public rewardsDistribution; function notifyRewardAmount(uint256 reward) external virtual; modifier onlyRewardsDistribution() { require(msg.sender == rewardsDistribution, "Caller is not RewardsDistribution contract"); _; } function setRewardsDistribution(address _rewardsDistribution) external onlyOwner { rewardsDistribution = _rewardsDistribution; } }
Address.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{value: value}(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall( target, data, "Address: low-level static call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
IERC20.sol
// SPDX-License-Identifier: MIT 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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval( address indexed owner, address indexed spender, uint256 value ); }
Math.sol
// SPDX-License-Identifier: MIT 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, so we distribute return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); } }
ReentrancyGuard.sol
// SPDX-License-Identifier: MIT 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 make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
SafeERC20.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + 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 // solhint-disable-next-line max-line-length require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } }
SafeMath.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_rewardsDistribution","internalType":"address"},{"type":"address","name":"_rewardsToken","internalType":"address"},{"type":"address","name":"_stakingToken","internalType":"address"}]},{"type":"event","name":"OwnerChanged","inputs":[{"type":"address","name":"oldOwner","internalType":"address","indexed":false},{"type":"address","name":"newOwner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerNominated","inputs":[{"type":"address","name":"newOwner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Recovered","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardAdded","inputs":[{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardPaid","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardsDurationUpdated","inputs":[{"type":"uint256","name":"newDuration","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawn","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"earned","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"exit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"getReward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRewardForDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastTimeRewardApplicable","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastUpdateTime","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"nominateNewOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"nominatedOwner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"notifyRewardAmount","inputs":[{"type":"uint256","name":"reward","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periodFinish","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverERC20","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"tokenAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardPerToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardPerTokenStored","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardRate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewards","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rewardsDistribution","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardsDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"rewardsToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRewardsDistribution","inputs":[{"type":"address","name":"_rewardsDistribution","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRewardsDuration","inputs":[{"type":"uint256","name":"_rewardsDuration","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"stakingToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePeriodFinish","inputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"userRewardPerTokenPaid","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]}]
Contract Creation Code
0x60806040526000600655600060075562093a806008553480156200002257600080fd5b5060405162002d7038038062002d70833981810160405281019062000048919062000225565b83600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620000bc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000b390620002f6565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008260405162000130929190620002c9565b60405180910390a150600160038190555081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050620003a0565b6000815190506200021f8162000386565b92915050565b600080600080608085870312156200023c57600080fd5b60006200024c878288016200020e565b94505060206200025f878288016200020e565b935050604062000272878288016200020e565b925050606062000285878288016200020e565b91505092959194509250565b6200029c8162000329565b82525050565b6000620002b160198362000318565b9150620002be826200035d565b602082019050919050565b6000604082019050620002e0600083018562000291565b620002ef602083018462000291565b9392505050565b600060208201905081810360008301526200031181620002a2565b9050919050565b600082825260208201905092915050565b600062000336826200033d565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000600082015250565b620003918162000329565b81146200039d57600080fd5b50565b6129c080620003b06000396000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806372f702f311610104578063a694fc3a116100a2578063d1af0c7d11610071578063d1af0c7d146104d1578063df136d65146104ef578063e9fad8ee1461050d578063ebe2b12b14610517576101ce565b8063a694fc3a1461045d578063c8f33c9114610479578063cc1a378f14610497578063cd3daf9d146104b3576101ce565b806380faa57d116100de57806380faa57d146103d55780638980f11f146103f35780638b8763471461040f5780638da5cb5b1461043f576101ce565b806372f702f31461038f57806379ba5097146103ad5780637b0a47ee146103b7576101ce565b8063386a9525116101715780633fc6df6e1161014b5780633fc6df6e1461030757806353a47bb714610325578063556f6e6b1461034357806370a082311461035f576101ce565b8063386a9525146102c35780633c6b16ab146102e15780633d18b912146102fd576101ce565b806318160ddd116101ad57806318160ddd1461024f578063197621431461026d5780631c1f78eb146102895780632e1a7d4d146102a7576101ce565b80628cc262146101d35780630700037d146102035780631627540c14610233575b600080fd5b6101ed60048036038101906101e89190611e26565b610535565b6040516101fa91906123b9565b60405180910390f35b61021d60048036038101906102189190611e26565b610653565b60405161022a91906123b9565b60405180910390f35b61024d60048036038101906102489190611e26565b61066b565b005b6102576106ee565b60405161026491906123b9565b60405180910390f35b61028760048036038101906102829190611e26565b6106f8565b005b610291610744565b60405161029e91906123b9565b60405180910390f35b6102c160048036038101906102bc9190611eb4565b610762565b005b6102cb610a2e565b6040516102d891906123b9565b60405180910390f35b6102fb60048036038101906102f69190611eb4565b610a34565b005b610305610d9a565b005b61030f611006565b60405161031c9190612158565b60405180910390f35b61032d61102c565b60405161033a9190612158565b60405180910390f35b61035d60048036038101906103589190611eb4565b611052565b005b61037960048036038101906103749190611e26565b61114a565b60405161038691906123b9565b60405180910390f35b610397611193565b6040516103a491906121fc565b60405180910390f35b6103b56111b9565b005b6103bf61136a565b6040516103cc91906123b9565b60405180910390f35b6103dd611370565b6040516103ea91906123b9565b60405180910390f35b61040d60048036038101906104089190611e4f565b611383565b005b61042960048036038101906104249190611e26565b6114a4565b60405161043691906123b9565b60405180910390f35b6104476114bc565b6040516104549190612158565b60405180910390f35b61047760048036038101906104729190611eb4565b6114e0565b005b6104816117ae565b60405161048e91906123b9565b60405180910390f35b6104b160048036038101906104ac9190611eb4565b6117b4565b005b6104bb611843565b6040516104c891906123b9565b60405180910390f35b6104d96118d1565b6040516104e691906121fc565b60405180910390f35b6104f76118f7565b60405161050491906123b9565b60405180910390f35b6105156118fd565b005b61051f61194f565b60405161052c91906123b9565b60405180910390f35b600061064c600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461063e670de0b6b3a76400006106306105e2600b60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546105d4611843565b61195590919063ffffffff16565b600e60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461196b90919063ffffffff16565b61198190919063ffffffff16565b61199790919063ffffffff16565b9050919050565b600c6020528060005260406000206000915090505481565b6106736119ad565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22816040516106e39190612158565b60405180910390a150565b6000600d54905090565b6107006119ad565b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061075d60085460075461196b90919063ffffffff16565b905090565b600260035414156107a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079f90612379565b60405180910390fd5b6002600381905550336107b9611843565b600a819055506107c7611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146108945761080a81610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600082116108d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ce906122d9565b60405180910390fd5b6108ec82600d5461195590919063ffffffff16565b600d8190555061094482600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461195590919063ffffffff16565b600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109d43383600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d583604051610a1a91906123b9565b60405180910390a250600160038190555050565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ac4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abb90612339565b60405180910390fd5b6000610ace611843565b600a81905550610adc611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ba957610b1f81610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6006544210610bd257610bc76008548361198190919063ffffffff16565b600781905550610c34565b6000610be94260065461195590919063ffffffff16565b90506000610c026007548361196b90919063ffffffff16565b9050610c2b600854610c1d838761199790919063ffffffff16565b61198190919063ffffffff16565b60078190555050505b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c919190612158565b60206040518083038186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce19190611edd565b9050610cf86008548261198190919063ffffffff16565b6007541115610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d33906122f9565b60405180910390fd5b42600981905550610d586008544261199790919063ffffffff16565b6006819055507fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d83604051610d8d91906123b9565b60405180910390a1505050565b60026003541415610de0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd790612379565b60405180910390fd5b600260038190555033610df1611843565b600a81905550610dff611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ecc57610e4281610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811115610ffa576000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610fab3382600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051610ff191906123b9565b60405180910390a25b50506001600381905550565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61105a6119ad565b6000611064611843565b600a81905550611072611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461113f576110b581610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b816006819055505050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124090612259565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516112bc929190612173565b60405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60075481565b600061137e42600654611ac3565b905090565b61138b6119ad565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561141c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141390612399565b60405180910390fd5b61146760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828473ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2882826040516114989291906121d3565b60405180910390a15050565b600b6020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026003541415611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d90612379565b60405180910390fd5b600260038190555033611537611843565b600a81905550611545611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146116125761158881610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008211611655576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164c90612279565b60405180910390fd5b61166a82600d5461199790919063ffffffff16565b600d819055506116c282600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461199790919063ffffffff16565b600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611754333084600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611adc909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8360405161179a91906123b9565b60405180910390a250600160038190555050565b60095481565b6117bc6119ad565b6006544211611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612239565b60405180910390fd5b806008819055507ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d360085460405161183891906123b9565b60405180910390a150565b600080600d54141561185957600a5490506118ce565b6118cb6118ba600d546118ac670de0b6b3a764000061189e600754611890600954611882611370565b61195590919063ffffffff16565b61196b90919063ffffffff16565b61196b90919063ffffffff16565b61198190919063ffffffff16565b600a5461199790919063ffffffff16565b90505b90565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a5481565b611945600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610762565b61194d610d9a565b565b60065481565b6000818361196391906124e7565b905092915050565b60008183611979919061248d565b905092915050565b6000818361198f919061245c565b905092915050565b600081836119a59190612406565b905092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a32906122b9565b60405180910390fd5b565b611abe8363a9059cbb60e01b8484604051602401611a5c9291906121d3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b65565b505050565b6000818310611ad25781611ad4565b825b905092915050565b611b5f846323b872dd60e01b858585604051602401611afd9392919061219c565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b65565b50505050565b6000611bc7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611c2c9092919063ffffffff16565b9050600081511115611c275780806020019051810190611be79190611e8b565b611c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1d90612359565b60405180910390fd5b5b505050565b6060611c3b8484600085611c44565b90509392505050565b606082471015611c89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8090612299565b60405180910390fd5b611c9285611d58565b611cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc890612319565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611cfa9190612141565b60006040518083038185875af1925050503d8060008114611d37576040519150601f19603f3d011682016040523d82523d6000602084013e611d3c565b606091505b5091509150611d4c828286611d6b565b92505050949350505050565b600080823b905060008111915050919050565b60608315611d7b57829050611dcb565b600083511115611d8e5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc29190612217565b60405180910390fd5b9392505050565b600081359050611de181612945565b92915050565b600081519050611df68161295c565b92915050565b600081359050611e0b81612973565b92915050565b600081519050611e2081612973565b92915050565b600060208284031215611e3857600080fd5b6000611e4684828501611dd2565b91505092915050565b60008060408385031215611e6257600080fd5b6000611e7085828601611dd2565b9250506020611e8185828601611dfc565b9150509250929050565b600060208284031215611e9d57600080fd5b6000611eab84828501611de7565b91505092915050565b600060208284031215611ec657600080fd5b6000611ed484828501611dfc565b91505092915050565b600060208284031215611eef57600080fd5b6000611efd84828501611e11565b91505092915050565b611f0f8161251b565b82525050565b6000611f20826123d4565b611f2a81856123ea565b9350611f3a818560208601612587565b80840191505092915050565b611f4f81612563565b82525050565b6000611f60826123df565b611f6a81856123f5565b9350611f7a818560208601612587565b611f8381612618565b840191505092915050565b6000611f9b6058836123f5565b9150611fa682612629565b606082019050919050565b6000611fbe6035836123f5565b9150611fc98261269e565b604082019050919050565b6000611fe1600e836123f5565b9150611fec826126ed565b602082019050919050565b60006120046026836123f5565b915061200f82612716565b604082019050919050565b6000612027602f836123f5565b915061203282612765565b604082019050919050565b600061204a6011836123f5565b9150612055826127b4565b602082019050919050565b600061206d6018836123f5565b9150612078826127dd565b602082019050919050565b6000612090601d836123f5565b915061209b82612806565b602082019050919050565b60006120b3602a836123f5565b91506120be8261282f565b604082019050919050565b60006120d6602a836123f5565b91506120e18261287e565b604082019050919050565b60006120f9601f836123f5565b9150612104826128cd565b602082019050919050565b600061211c6021836123f5565b9150612127826128f6565b604082019050919050565b61213b81612559565b82525050565b600061214d8284611f15565b915081905092915050565b600060208201905061216d6000830184611f06565b92915050565b60006040820190506121886000830185611f06565b6121956020830184611f06565b9392505050565b60006060820190506121b16000830186611f06565b6121be6020830185611f06565b6121cb6040830184612132565b949350505050565b60006040820190506121e86000830185611f06565b6121f56020830184612132565b9392505050565b60006020820190506122116000830184611f46565b92915050565b600060208201905081810360008301526122318184611f55565b905092915050565b6000602082019050818103600083015261225281611f8e565b9050919050565b6000602082019050818103600083015261227281611fb1565b9050919050565b6000602082019050818103600083015261229281611fd4565b9050919050565b600060208201905081810360008301526122b281611ff7565b9050919050565b600060208201905081810360008301526122d28161201a565b9050919050565b600060208201905081810360008301526122f28161203d565b9050919050565b6000602082019050818103600083015261231281612060565b9050919050565b6000602082019050818103600083015261233281612083565b9050919050565b60006020820190508181036000830152612352816120a6565b9050919050565b60006020820190508181036000830152612372816120c9565b9050919050565b60006020820190508181036000830152612392816120ec565b9050919050565b600060208201905081810360008301526123b28161210f565b9050919050565b60006020820190506123ce6000830184612132565b92915050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b600061241182612559565b915061241c83612559565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612451576124506125ba565b5b828201905092915050565b600061246782612559565b915061247283612559565b925082612482576124816125e9565b5b828204905092915050565b600061249882612559565b91506124a383612559565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156124dc576124db6125ba565b5b828202905092915050565b60006124f282612559565b91506124fd83612559565b9250828210156125105761250f6125ba565b5b828203905092915050565b600061252682612539565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061256e82612575565b9050919050565b600061258082612539565b9050919050565b60005b838110156125a557808201518184015260208101905061258a565b838111156125b4576000848401525b50505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000601f19601f8301169050919050565b7f50726576696f7573207265776172647320706572696f64206d7573742062652060008201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260208201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000604082015250565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560008201527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015250565b7f43616e6e6f74207374616b652030000000000000000000000000000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660008201527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015250565b7f43616e6e6f742077697468647261772030000000000000000000000000000000600082015250565b7f50726f76696465642072657761726420746f6f20686967680000000000000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f43616c6c6572206973206e6f742052657761726473446973747269627574696f60008201527f6e20636f6e747261637400000000000000000000000000000000000000000000602082015250565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b61294e8161251b565b811461295957600080fd5b50565b6129658161252d565b811461297057600080fd5b50565b61297c81612559565b811461298757600080fd5b5056fea264697066735822122014371202a5cf77bb1b051f0519a9118211d27941f3a24cc16508139f9d5c9bc964736f6c634300080300330000000000000000000000001051834fc333f9e4b6a78c3e914d9094f57f33bd0000000000000000000000001051834fc333f9e4b6a78c3e914d9094f57f33bd000000000000000000000000ba647ff9b1032ca3aa7f7cc9e33d55785f49cd8e0000000000000000000000003a820bba932c7f85ce3c6736d1be982e779b5fa8
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101ce5760003560e01c806372f702f311610104578063a694fc3a116100a2578063d1af0c7d11610071578063d1af0c7d146104d1578063df136d65146104ef578063e9fad8ee1461050d578063ebe2b12b14610517576101ce565b8063a694fc3a1461045d578063c8f33c9114610479578063cc1a378f14610497578063cd3daf9d146104b3576101ce565b806380faa57d116100de57806380faa57d146103d55780638980f11f146103f35780638b8763471461040f5780638da5cb5b1461043f576101ce565b806372f702f31461038f57806379ba5097146103ad5780637b0a47ee146103b7576101ce565b8063386a9525116101715780633fc6df6e1161014b5780633fc6df6e1461030757806353a47bb714610325578063556f6e6b1461034357806370a082311461035f576101ce565b8063386a9525146102c35780633c6b16ab146102e15780633d18b912146102fd576101ce565b806318160ddd116101ad57806318160ddd1461024f578063197621431461026d5780631c1f78eb146102895780632e1a7d4d146102a7576101ce565b80628cc262146101d35780630700037d146102035780631627540c14610233575b600080fd5b6101ed60048036038101906101e89190611e26565b610535565b6040516101fa91906123b9565b60405180910390f35b61021d60048036038101906102189190611e26565b610653565b60405161022a91906123b9565b60405180910390f35b61024d60048036038101906102489190611e26565b61066b565b005b6102576106ee565b60405161026491906123b9565b60405180910390f35b61028760048036038101906102829190611e26565b6106f8565b005b610291610744565b60405161029e91906123b9565b60405180910390f35b6102c160048036038101906102bc9190611eb4565b610762565b005b6102cb610a2e565b6040516102d891906123b9565b60405180910390f35b6102fb60048036038101906102f69190611eb4565b610a34565b005b610305610d9a565b005b61030f611006565b60405161031c9190612158565b60405180910390f35b61032d61102c565b60405161033a9190612158565b60405180910390f35b61035d60048036038101906103589190611eb4565b611052565b005b61037960048036038101906103749190611e26565b61114a565b60405161038691906123b9565b60405180910390f35b610397611193565b6040516103a491906121fc565b60405180910390f35b6103b56111b9565b005b6103bf61136a565b6040516103cc91906123b9565b60405180910390f35b6103dd611370565b6040516103ea91906123b9565b60405180910390f35b61040d60048036038101906104089190611e4f565b611383565b005b61042960048036038101906104249190611e26565b6114a4565b60405161043691906123b9565b60405180910390f35b6104476114bc565b6040516104549190612158565b60405180910390f35b61047760048036038101906104729190611eb4565b6114e0565b005b6104816117ae565b60405161048e91906123b9565b60405180910390f35b6104b160048036038101906104ac9190611eb4565b6117b4565b005b6104bb611843565b6040516104c891906123b9565b60405180910390f35b6104d96118d1565b6040516104e691906121fc565b60405180910390f35b6104f76118f7565b60405161050491906123b9565b60405180910390f35b6105156118fd565b005b61051f61194f565b60405161052c91906123b9565b60405180910390f35b600061064c600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461063e670de0b6b3a76400006106306105e2600b60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546105d4611843565b61195590919063ffffffff16565b600e60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461196b90919063ffffffff16565b61198190919063ffffffff16565b61199790919063ffffffff16565b9050919050565b600c6020528060005260406000206000915090505481565b6106736119ad565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22816040516106e39190612158565b60405180910390a150565b6000600d54905090565b6107006119ad565b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061075d60085460075461196b90919063ffffffff16565b905090565b600260035414156107a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079f90612379565b60405180910390fd5b6002600381905550336107b9611843565b600a819055506107c7611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146108945761080a81610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600082116108d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ce906122d9565b60405180910390fd5b6108ec82600d5461195590919063ffffffff16565b600d8190555061094482600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461195590919063ffffffff16565b600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109d43383600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d583604051610a1a91906123b9565b60405180910390a250600160038190555050565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ac4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abb90612339565b60405180910390fd5b6000610ace611843565b600a81905550610adc611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ba957610b1f81610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6006544210610bd257610bc76008548361198190919063ffffffff16565b600781905550610c34565b6000610be94260065461195590919063ffffffff16565b90506000610c026007548361196b90919063ffffffff16565b9050610c2b600854610c1d838761199790919063ffffffff16565b61198190919063ffffffff16565b60078190555050505b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c919190612158565b60206040518083038186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce19190611edd565b9050610cf86008548261198190919063ffffffff16565b6007541115610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d33906122f9565b60405180910390fd5b42600981905550610d586008544261199790919063ffffffff16565b6006819055507fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d83604051610d8d91906123b9565b60405180910390a1505050565b60026003541415610de0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd790612379565b60405180910390fd5b600260038190555033610df1611843565b600a81905550610dff611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ecc57610e4281610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811115610ffa576000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610fab3382600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051610ff191906123b9565b60405180910390a25b50506001600381905550565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61105a6119ad565b6000611064611843565b600a81905550611072611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461113f576110b581610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b816006819055505050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124090612259565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516112bc929190612173565b60405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60075481565b600061137e42600654611ac3565b905090565b61138b6119ad565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561141c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141390612399565b60405180910390fd5b61146760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828473ffffffffffffffffffffffffffffffffffffffff16611a3d9092919063ffffffff16565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2882826040516114989291906121d3565b60405180910390a15050565b600b6020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026003541415611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d90612379565b60405180910390fd5b600260038190555033611537611843565b600a81905550611545611370565b600981905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146116125761158881610535565b600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600a54600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008211611655576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164c90612279565b60405180910390fd5b61166a82600d5461199790919063ffffffff16565b600d819055506116c282600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461199790919063ffffffff16565b600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611754333084600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611adc909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8360405161179a91906123b9565b60405180910390a250600160038190555050565b60095481565b6117bc6119ad565b6006544211611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612239565b60405180910390fd5b806008819055507ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d360085460405161183891906123b9565b60405180910390a150565b600080600d54141561185957600a5490506118ce565b6118cb6118ba600d546118ac670de0b6b3a764000061189e600754611890600954611882611370565b61195590919063ffffffff16565b61196b90919063ffffffff16565b61196b90919063ffffffff16565b61198190919063ffffffff16565b600a5461199790919063ffffffff16565b90505b90565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a5481565b611945600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610762565b61194d610d9a565b565b60065481565b6000818361196391906124e7565b905092915050565b60008183611979919061248d565b905092915050565b6000818361198f919061245c565b905092915050565b600081836119a59190612406565b905092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a32906122b9565b60405180910390fd5b565b611abe8363a9059cbb60e01b8484604051602401611a5c9291906121d3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b65565b505050565b6000818310611ad25781611ad4565b825b905092915050565b611b5f846323b872dd60e01b858585604051602401611afd9392919061219c565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b65565b50505050565b6000611bc7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611c2c9092919063ffffffff16565b9050600081511115611c275780806020019051810190611be79190611e8b565b611c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1d90612359565b60405180910390fd5b5b505050565b6060611c3b8484600085611c44565b90509392505050565b606082471015611c89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8090612299565b60405180910390fd5b611c9285611d58565b611cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc890612319565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611cfa9190612141565b60006040518083038185875af1925050503d8060008114611d37576040519150601f19603f3d011682016040523d82523d6000602084013e611d3c565b606091505b5091509150611d4c828286611d6b565b92505050949350505050565b600080823b905060008111915050919050565b60608315611d7b57829050611dcb565b600083511115611d8e5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc29190612217565b60405180910390fd5b9392505050565b600081359050611de181612945565b92915050565b600081519050611df68161295c565b92915050565b600081359050611e0b81612973565b92915050565b600081519050611e2081612973565b92915050565b600060208284031215611e3857600080fd5b6000611e4684828501611dd2565b91505092915050565b60008060408385031215611e6257600080fd5b6000611e7085828601611dd2565b9250506020611e8185828601611dfc565b9150509250929050565b600060208284031215611e9d57600080fd5b6000611eab84828501611de7565b91505092915050565b600060208284031215611ec657600080fd5b6000611ed484828501611dfc565b91505092915050565b600060208284031215611eef57600080fd5b6000611efd84828501611e11565b91505092915050565b611f0f8161251b565b82525050565b6000611f20826123d4565b611f2a81856123ea565b9350611f3a818560208601612587565b80840191505092915050565b611f4f81612563565b82525050565b6000611f60826123df565b611f6a81856123f5565b9350611f7a818560208601612587565b611f8381612618565b840191505092915050565b6000611f9b6058836123f5565b9150611fa682612629565b606082019050919050565b6000611fbe6035836123f5565b9150611fc98261269e565b604082019050919050565b6000611fe1600e836123f5565b9150611fec826126ed565b602082019050919050565b60006120046026836123f5565b915061200f82612716565b604082019050919050565b6000612027602f836123f5565b915061203282612765565b604082019050919050565b600061204a6011836123f5565b9150612055826127b4565b602082019050919050565b600061206d6018836123f5565b9150612078826127dd565b602082019050919050565b6000612090601d836123f5565b915061209b82612806565b602082019050919050565b60006120b3602a836123f5565b91506120be8261282f565b604082019050919050565b60006120d6602a836123f5565b91506120e18261287e565b604082019050919050565b60006120f9601f836123f5565b9150612104826128cd565b602082019050919050565b600061211c6021836123f5565b9150612127826128f6565b604082019050919050565b61213b81612559565b82525050565b600061214d8284611f15565b915081905092915050565b600060208201905061216d6000830184611f06565b92915050565b60006040820190506121886000830185611f06565b6121956020830184611f06565b9392505050565b60006060820190506121b16000830186611f06565b6121be6020830185611f06565b6121cb6040830184612132565b949350505050565b60006040820190506121e86000830185611f06565b6121f56020830184612132565b9392505050565b60006020820190506122116000830184611f46565b92915050565b600060208201905081810360008301526122318184611f55565b905092915050565b6000602082019050818103600083015261225281611f8e565b9050919050565b6000602082019050818103600083015261227281611fb1565b9050919050565b6000602082019050818103600083015261229281611fd4565b9050919050565b600060208201905081810360008301526122b281611ff7565b9050919050565b600060208201905081810360008301526122d28161201a565b9050919050565b600060208201905081810360008301526122f28161203d565b9050919050565b6000602082019050818103600083015261231281612060565b9050919050565b6000602082019050818103600083015261233281612083565b9050919050565b60006020820190508181036000830152612352816120a6565b9050919050565b60006020820190508181036000830152612372816120c9565b9050919050565b60006020820190508181036000830152612392816120ec565b9050919050565b600060208201905081810360008301526123b28161210f565b9050919050565b60006020820190506123ce6000830184612132565b92915050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b600061241182612559565b915061241c83612559565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612451576124506125ba565b5b828201905092915050565b600061246782612559565b915061247283612559565b925082612482576124816125e9565b5b828204905092915050565b600061249882612559565b91506124a383612559565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156124dc576124db6125ba565b5b828202905092915050565b60006124f282612559565b91506124fd83612559565b9250828210156125105761250f6125ba565b5b828203905092915050565b600061252682612539565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061256e82612575565b9050919050565b600061258082612539565b9050919050565b60005b838110156125a557808201518184015260208101905061258a565b838111156125b4576000848401525b50505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000601f19601f8301169050919050565b7f50726576696f7573207265776172647320706572696f64206d7573742062652060008201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260208201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000604082015250565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560008201527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015250565b7f43616e6e6f74207374616b652030000000000000000000000000000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660008201527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015250565b7f43616e6e6f742077697468647261772030000000000000000000000000000000600082015250565b7f50726f76696465642072657761726420746f6f20686967680000000000000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f43616c6c6572206973206e6f742052657761726473446973747269627574696f60008201527f6e20636f6e747261637400000000000000000000000000000000000000000000602082015250565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b61294e8161251b565b811461295957600080fd5b50565b6129658161252d565b811461297057600080fd5b50565b61297c81612559565b811461298757600080fd5b5056fea264697066735822122014371202a5cf77bb1b051f0519a9118211d27941f3a24cc16508139f9d5c9bc964736f6c63430008030033