Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- StakingBeta
- Optimization enabled
- false
- Compiler version
- v0.8.22+commit.4fc1097e
- Verified at
- 2025-05-15T05:23:45.541537Z
contracts/Ame/StakingBeta.sol
// Author : AME Chain // Version : 1.4.0 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; /** * @title Staking Contract * @dev This contract allows users to stake tokens in various pools, earning rewards over time. * It supports both native AME tokens and ERC20 tokens. */ contract StakingBeta is Ownable, ReentrancyGuard { using SafeERC20 for IERC20; enum Status { Staked, Pending, Completed } // --------------------- STRUCTS --------------------- /// @dev Stores details of a staking pool struct Pool { uint256 poolId; // Unique Pool Identifier bool isNative; // Indicates if the pool uses native AME or ERC20 token IERC20 token; // ERC20 token contract address (address(0) for native) uint256 apr; // Annual Percentage Rate for rewards uint256 lockDuration; // Duration in seconds for locked staking bool isActive; // Pool activation status } /// @dev Stores details of a user's stake struct StakingDetails { uint256 stakedAmount; // Amount staked by the user uint256 startTime; // Timestamp when stake was created uint256 poolId; // ID of the pool uint256 lockDuration; // Duration in seconds for locked staking uint256 rewardsEarned; // Accumulated rewards Status status; // Current status of the stake } /// @dev Stores user-friendly data of a user's stake struct StakingUserData { uint256 stakeId; // Index of the user's stake uint256 amount; // Amount staked uint256 startTime; // Stake start timestamp uint256 endTime; // Stake end timestamp (if locked) uint256 poolId; // Pool ID uint256 apr; // APR of the pool uint256 lockDuration; // Lock duration of the pool bool isNative; // Whether the pool uses native AME or ERC20 IERC20 token; // Pool's token contract uint256 rewardsEarned; // Rewards earned Status status; // Current status of the stake } /// @dev Stores unstake request details struct UnstakeRequest { uint256 requestId; // Unique request Identifier address user; // User who made the request uint256 stakeIndex; // Index of the stake uint256 amount; // Staked amount uint256 reward; // Reward amount uint256 timestamp; // Timestamp of the request Status status; // Current status of the stake } // --------------------- STATE VARIABLES ------------- uint256 private constant SECONDS_IN_YEAR = 365 days; // Seconds in a year for APR calculations uint256 private constant PRECISION = 1e6; // Precision factor for calculations uint256 public minimumStakeDuration; // Minimum duration a stake must be held uint256 public minimumStakeAmount; // Minimum Amount a stake must be have uint256 private poolCount; // Counter for pool IDs address public treasury; // Treasury address to receive staked tokens // Mappings mapping(uint256 => Pool) private pools; // Mapping of pool ID to pool details mapping(address => bool) private managers; // Contract Managers mapping(address => mapping(uint256 => StakingDetails)) private userStakes; // Mapping of user address to stake index to stake details mapping(address => uint256) private userStakeCount; // Mapping of user address to their total stake count mapping(uint256 => uint256) public totalStakedPerPool; // Mapping of pool ID to total staked amount in the pool mapping(uint256 => mapping(uint256 => UnstakeRequest)) private unstakeRequests; // Mapping of pool ID to request ID to unstake request details mapping(uint256 => uint256) public unstakeRequestCount; // poolId => requestId counter // --------------------- EVENTS ---------------------- event Staked( address indexed user, uint256 amount, uint256 poolId, uint256 stakeIndex, uint256 timestamp ); event UnstakeRequested( address indexed user, uint256 poolId, uint256 stakeIndex, uint256 amount, uint256 reward, uint256 timestamp ); event RequestCompleted( address indexed user, uint256 poolId, uint256 stakeIndex, uint256 amount, uint256 timestamp ); event PoolCreated( uint256 indexed poolId, uint256 apr, uint256 lockDuration, uint256 timestamp ); event PoolUpdated(uint256 indexed poolId, bool isActive, uint256 timestamp); // --------------------- CONSTRUCTOR ----------------- constructor() Ownable() { minimumStakeDuration = 7 days; // Default minimum stake duration minimumStakeAmount = 10 * 10 ** 18; } // --------------------- MODIFIERS ------------------- modifier validPool(uint256 _poolId) { require(_poolId < poolCount, "Invalid pool ID"); require(pools[_poolId].isActive, "Pool is not active"); _; } modifier isManager() { require(managers[msg.sender] == true, "Not an Manager"); _; } // --------------------- POOL MANAGEMENT ------------- /// @notice Creates a new staking pool /// @param _isNative Whether the pool uses native AME /// @param _token ERC20 token address (address(0) for native) /// @param _apr Annual Percentage Rate for rewards /// @param _lockDuration Duration in seconds for locked staking function createPool( bool _isNative, address _token, uint256 _apr, uint256 _lockDuration ) external nonReentrant isManager { require( (_isNative && _token == address(0)) || (!_isNative && _token != address(0)), "Invalid token" ); require(_apr > 0, "APR must be greater than 0"); require( _lockDuration == 0 || _lockDuration >= 7 days, "Invalid Lock Duration" ); pools[poolCount] = Pool({ poolId: poolCount, isNative: _isNative, token: IERC20(_token), apr: _apr, lockDuration: _lockDuration, isActive: true }); emit PoolCreated(poolCount, _apr, _lockDuration, block.timestamp); poolCount++; } /// @notice Updates the status of a pool /// @param _poolId ID of the pool to update /// @param _isActive New status of the pool function updatePoolStatus( uint256 _poolId, bool _isActive ) external isManager { require(_poolId < poolCount, "Invalid pool ID"); pools[_poolId].isActive = _isActive; emit PoolUpdated(_poolId, _isActive, block.timestamp); } /// @notice Retrieves all active pools /// @param offset Starting index to search for active pools /// @param limit Maximum number of active pools to return /// @return Array of active pool details function getActivePools( uint256 offset, uint256 limit ) external view returns (Pool[] memory) { Pool[] memory temp = new Pool[](limit); uint256 count; uint256 found; for (uint256 i = 0; i < poolCount && count < offset + limit; i++) { if (pools[i].isActive) { if (count >= offset) { temp[found] = pools[i]; found++; } count++; } } Pool[] memory activePools = new Pool[](found); for (uint256 i = 0; i < found; i++) { activePools[i] = temp[i]; } return activePools; } /// @notice Retrieves all pools with pagination /// @param offset Starting index /// @param limit Maximum number of pools to return /// @return Array of pool details function getAllPools( uint256 offset, uint256 limit ) external view returns (Pool[] memory) { require(offset <= poolCount, "Invalid Offset"); uint256 end = offset + limit > poolCount ? poolCount : offset + limit; uint256 size = end - offset; Pool[] memory result = new Pool[](size); for (uint256 i = 0; i < size; i++) { result[i] = pools[offset + i]; } return result; } /// @notice Returns the total number of pools /// @return Total pool count function getPoolCount() external view returns (uint256) { return poolCount; } // --------------------- STAKING OPERATIONS ---------- /// @notice Allows a user to stake tokens in a pool /// @param _poolId ID of the pool to stake in /// @param _amount Amount to stake function stake( uint256 _poolId, uint256 _amount ) external payable nonReentrant validPool(_poolId) { require(_amount >= minimumStakeAmount, "Invalid Stake Amount"); Pool memory pool = pools[_poolId]; if (pool.isNative) { require(msg.value == _amount, "Incorrect AME amount"); payable(treasury).transfer(_amount); } else { require(msg.value == 0, "No AME needed"); pool.token.safeTransferFrom(msg.sender, treasury, _amount); } uint256 stakeIndex = userStakeCount[msg.sender]; userStakes[msg.sender][stakeIndex] = StakingDetails({ stakedAmount: _amount, startTime: block.timestamp, lockDuration: pool.lockDuration, poolId: _poolId, rewardsEarned: 0, status: Status.Staked }); userStakeCount[msg.sender]++; totalStakedPerPool[_poolId] += _amount; emit Staked(msg.sender, _amount, _poolId, stakeIndex, block.timestamp); } /// @notice Requests to unstake tokens /// @param _stakeIndex Index of the stake to unstake function requestUnstake(uint256 _stakeIndex) external nonReentrant { require( _stakeIndex < userStakeCount[msg.sender], "Invalid stake index" ); StakingDetails storage stakeData = userStakes[msg.sender][_stakeIndex]; require(stakeData.status == Status.Staked, "Stake not active"); require( block.timestamp >= stakeData.startTime + stakeData.lockDuration + minimumStakeDuration, "Stake still locked" ); // enforce minimum stake duration of variable uint256 reward = calculateReward(msg.sender, _stakeIndex); stakeData.rewardsEarned = reward; stakeData.status = Status.Pending; uint256 requestId = unstakeRequestCount[stakeData.poolId]++; unstakeRequests[stakeData.poolId][requestId] = UnstakeRequest({ requestId: requestId, user: msg.sender, stakeIndex: _stakeIndex, amount: stakeData.stakedAmount, reward: reward, timestamp: block.timestamp, status: Status.Pending }); totalStakedPerPool[stakeData.poolId] -= stakeData.stakedAmount; emit UnstakeRequested( msg.sender, stakeData.poolId, _stakeIndex, stakeData.stakedAmount, reward, block.timestamp ); } /// @notice Completes an unstake request and transfers rewards to the user /// @param _poolId Id of Requested Pool /// @param _requestIndex Index of the request function completeUnstake( uint256 _poolId, uint256 _requestIndex ) external payable isManager nonReentrant { require( _requestIndex < unstakeRequestCount[_poolId], "Invalid Stake Index" ); require(_poolId < poolCount, "Invalid Pool Index"); UnstakeRequest storage request = unstakeRequests[_poolId][ _requestIndex ]; require(request.status == Status.Pending, "Request not pending"); StakingDetails storage stakeData = userStakes[request.user][ request.stakeIndex ]; require(stakeData.status == Status.Pending, "Request not pending"); Pool memory pool = pools[stakeData.poolId]; uint256 reward = stakeData.rewardsEarned; uint256 totalAmount = stakeData.stakedAmount + reward; stakeData.status = Status.Completed; request.status = Status.Completed; if (pool.isNative) { require(msg.value >= totalAmount, "Incorrect AME amount"); // can add precision payable(request.user).transfer(totalAmount); } else { require( pool.token.balanceOf(msg.sender) >= totalAmount, "Insufficient token balance" ); require(msg.value == 0, "No AME needed"); pool.token.safeTransferFrom(msg.sender, request.user, totalAmount); } emit RequestCompleted( request.user, stakeData.poolId, _requestIndex, totalAmount, block.timestamp ); } // --------------------- REWARD MANAGEMENT ----------- /// @notice Calculates the reward for a stake /// @param _user Address of the user /// @param _stakeIndex Index of the stake /// @return Calculated reward amount function calculateReward( address _user, uint256 _stakeIndex ) private view returns (uint256) { require(_stakeIndex < userStakeCount[_user], "Invalid stake index"); StakingDetails memory stakeData = userStakes[_user][_stakeIndex]; if (stakeData.status != Status.Staked) return stakeData.rewardsEarned; Pool memory pool = pools[stakeData.poolId]; uint256 stakingDuration = block.timestamp - stakeData.startTime; if ( stakeData.lockDuration > 0 && stakingDuration > stakeData.lockDuration ) { stakingDuration = stakeData.lockDuration; } // Rewards Calculates till lock duration // Reward = (amount * APR * duration) / (100 * seconds_in_year) uint256 reward = (stakeData.stakedAmount * pool.apr * stakingDuration * PRECISION) / (100 * SECONDS_IN_YEAR * PRECISION); return reward; } // --------------------- UTILITY FUNCTIONS ----------- /// @notice Updates the Minimum Stake Duration /// @param _minDuration New Minimum Stake Duration function setMinimumStakeDuration( uint256 _minDuration ) external isManager nonReentrant { require(_minDuration >= 0, "Invalid Duration"); minimumStakeDuration = _minDuration; } /// @notice Updates the Minimum Stake Amount /// @param _minAmount New Minimum Stake Amount function setMinimumStakeAmount( uint256 _minAmount ) external isManager nonReentrant { require(_minAmount >= 0, "Invalid Amount"); minimumStakeAmount = _minAmount; } /// @notice Updates the mini address /// @param _treasury New treasury address function setTreasury(address _treasury) external isManager nonReentrant { require(_treasury != address(0), "Invalid treasury address"); treasury = _treasury; } /// @notice Adds or removes a manager. /// @param _manager Address of the manager to be added or removed. /// @param status True to add the manager, false to remove the manager. function manageManager( address _manager, bool status ) external onlyOwner nonReentrant { managers[_manager] = status; } /// @notice Checks if the given address is a manager. /// @param _manager The address to verify. /// @return True if the address is a verified manager, false otherwise. function verifyManager(address _manager) external view returns (bool) { return managers[_manager]; } /// @notice Retrieves a paginated list of stakes for a user /// @param _user Address of the user /// @param offset Starting index of the stakes to return /// @param limit Maximum number of stakes to return /// @return Array of user stake details function getUserStakes( address _user, uint256 offset, uint256 limit ) external view returns (StakingUserData[] memory) { uint256 start = offset; uint256 end = offset + limit > userStakeCount[_user] ? userStakeCount[_user] : offset + limit; uint256 size = end - start; StakingUserData[] memory stakes = new StakingUserData[](size); for (uint256 i = 0; i < size; i++) { uint256 stakeIndex = offset + i; StakingDetails memory stakeData = userStakes[_user][stakeIndex]; Pool memory pool = pools[stakeData.poolId]; uint256 reward = calculateReward(_user, stakeIndex); uint256 endTime = stakeData.lockDuration > 0 ? stakeData.startTime + stakeData.lockDuration : 0; stakes[i] = StakingUserData({ stakeId: stakeIndex, amount: stakeData.stakedAmount, startTime: stakeData.startTime, endTime: endTime, poolId: stakeData.poolId, apr: pool.apr, lockDuration: stakeData.lockDuration, isNative: pool.isNative, token: pool.token, rewardsEarned: reward, status: stakeData.status }); } return stakes; } /// @notice Returns the total number of stakes by a user /// @param _user Address of the user /// @return Total number of user stakes function getUserTotalStakes(address _user) external view returns (uint256) { return userStakeCount[_user]; } /// @notice Retrieves unstake requests /// @param poolId starting index_poolId /// @param offset starting index /// @param limit number of requests /// @return Array of unstake request details function getUnstakeRequests( uint256 poolId, uint256 offset, uint256 limit ) external view returns (UnstakeRequest[] memory) { uint256 requestCount = unstakeRequestCount[poolId]; require(poolId < poolCount, "Invalid pool ID"); require(offset < requestCount, "Offset out of bounds"); uint256 end = offset + limit > requestCount ? requestCount : offset + limit; uint256 size = end - offset; UnstakeRequest[] memory requests = new UnstakeRequest[](size); for (uint256 i = 0; i < size; i++) { requests[i] = unstakeRequests[poolId][offset + i]; } return requests; } /// @notice Withdraws excess funds from contract function withdrawExcessFunds() external isManager nonReentrant { uint256 contractBalance = address(this).balance; (bool sent, ) = msg.sender.call{value: contractBalance}(""); require(sent, "Failed to send OZOs"); } }
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/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; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @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 Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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); } }
@openzeppelin/contracts/security/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (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() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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); }
@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":false},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PoolCreated","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"apr","internalType":"uint256","indexed":false},{"type":"uint256","name":"lockDuration","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PoolUpdated","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"bool","name":"isActive","internalType":"bool","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RequestCompleted","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":false},{"type":"uint256","name":"stakeIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","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},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":false},{"type":"uint256","name":"stakeIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"UnstakeRequested","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":false},{"type":"uint256","name":"stakeIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[],"name":"completeUnstake","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_requestIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createPool","inputs":[{"type":"bool","name":"_isNative","internalType":"bool"},{"type":"address","name":"_token","internalType":"address"},{"type":"uint256","name":"_apr","internalType":"uint256"},{"type":"uint256","name":"_lockDuration","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct StakingBeta.Pool[]","components":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"bool","name":"isNative","internalType":"bool"},{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"apr","internalType":"uint256"},{"type":"uint256","name":"lockDuration","internalType":"uint256"},{"type":"bool","name":"isActive","internalType":"bool"}]}],"name":"getActivePools","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct StakingBeta.Pool[]","components":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"bool","name":"isNative","internalType":"bool"},{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"apr","internalType":"uint256"},{"type":"uint256","name":"lockDuration","internalType":"uint256"},{"type":"bool","name":"isActive","internalType":"bool"}]}],"name":"getAllPools","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPoolCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct StakingBeta.UnstakeRequest[]","components":[{"type":"uint256","name":"requestId","internalType":"uint256"},{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"stakeIndex","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"reward","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum StakingBeta.Status"}]}],"name":"getUnstakeRequests","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct StakingBeta.StakingUserData[]","components":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startTime","internalType":"uint256"},{"type":"uint256","name":"endTime","internalType":"uint256"},{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"apr","internalType":"uint256"},{"type":"uint256","name":"lockDuration","internalType":"uint256"},{"type":"bool","name":"isNative","internalType":"bool"},{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"rewardsEarned","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum StakingBeta.Status"}]}],"name":"getUserStakes","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUserTotalStakes","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"manageManager","inputs":[{"type":"address","name":"_manager","internalType":"address"},{"type":"bool","name":"status","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minimumStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minimumStakeDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"requestUnstake","inputs":[{"type":"uint256","name":"_stakeIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinimumStakeAmount","inputs":[{"type":"uint256","name":"_minAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinimumStakeDuration","inputs":[{"type":"uint256","name":"_minDuration","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTreasury","inputs":[{"type":"address","name":"_treasury","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStakedPerPool","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"treasury","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"unstakeRequestCount","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePoolStatus","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"bool","name":"_isActive","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyManager","inputs":[{"type":"address","name":"_manager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawExcessFunds","inputs":[]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b5062000032620000266200005860201b60201c565b6200006060201b60201c565b6001808190555062093a80600281905550678ac7230489e8000060038190555062000124565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b614eff80620001346000396000f3fe6080604052600436106101665760003560e01c8063722b4b32116100d1578063a7753f091161008a578063c9b8981711610064578063c9b8981714610532578063f0f442601461056f578063f2fde38b14610598578063fcb67c5b146105c157610166565b8063a7753f09146104a1578063a8bd7300146104de578063b8f49d8f1461050957610166565b8063722b4b32146103995780637b0472f0146103d65780638da5cb5b146103f25780638eec5d701461041d5780639433773014610448578063969d68581461046457610166565b8063560e878311610123578063560e878314610289578063603edf55146102b257806361d027b3146102ef5780636a6c8d8b1461031a5780636b036f4514610357578063715018a61461038257610166565b80630bc313a61461016b5780630d29fcd41461019457806323095721146101bd57806324df6bee146101e657806338864e2114610223578063392cb1c214610260575b600080fd5b34801561017757600080fd5b50610192600480360381019061018d91906135a4565b6105d8565b005b3480156101a057600080fd5b506101bb60048036038101906101b6919061360b565b61092c565b005b3480156101c957600080fd5b506101e460048036038101906101df919061360b565b610a1d565b005b3480156101f257600080fd5b5061020d6004803603810190610208919061360b565b610e1b565b60405161021a9190613647565b60405180910390f35b34801561022f57600080fd5b5061024a60048036038101906102459190613662565b610e33565b6040516102579190613647565b60405180910390f35b34801561026c57600080fd5b506102876004803603810190610282919061360b565b610e7c565b005b34801561029557600080fd5b506102b060048036038101906102ab919061368f565b610f6d565b005b3480156102be57600080fd5b506102d960048036038101906102d491906136cf565b6110b0565b6040516102e691906138f4565b60405180910390f35b3480156102fb57600080fd5b50610304611323565b6040516103119190613925565b60405180910390f35b34801561032657600080fd5b50610341600480360381019061033c9190613940565b611349565b60405161034e9190613b92565b60405180910390f35b34801561036357600080fd5b5061036c611724565b6040516103799190613647565b60405180910390f35b34801561038e57600080fd5b5061039761172a565b005b3480156103a557600080fd5b506103c060048036038101906103bb919061360b565b61173e565b6040516103cd9190613647565b60405180910390f35b6103f060048036038101906103eb9190613bb4565b611756565b005b3480156103fe57600080fd5b50610407611c88565b6040516104149190613925565b60405180910390f35b34801561042957600080fd5b50610432611cb1565b60405161043f9190613647565b60405180910390f35b610462600480360381019061045d9190613bb4565b611cbb565b005b34801561047057600080fd5b5061048b60048036038101906104869190613bb4565b61236d565b6040516104989190613d1e565b60405180910390f35b3480156104ad57600080fd5b506104c860048036038101906104c39190613bb4565b6125ec565b6040516104d59190613d1e565b60405180910390f35b3480156104ea57600080fd5b506104f36127de565b6040516105009190613647565b60405180910390f35b34801561051557600080fd5b50610530600480360381019061052b9190613d40565b6127e4565b005b34801561053e57600080fd5b5061055960048036038101906105549190613662565b612857565b6040516105669190613d8f565b60405180910390f35b34801561057b57600080fd5b5061059660048036038101906105919190613662565b6128ad565b005b3480156105a457600080fd5b506105bf60048036038101906105ba9190613662565b612a03565b005b3480156105cd57600080fd5b506105d6612a86565b005b6105e0612bde565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066a90613e07565b60405180910390fd5b8380156106ac5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b806106ee5750831580156106ed5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b5b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072490613e73565b60405180910390fd5b60008211610770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076790613edf565b60405180910390fd5b6000811480610782575062093a808110155b6107c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b890613f4b565b60405180910390fd5b6040518060c00160405280600454815260200185151581526020018473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001600115158152506006600060045481526020019081526020016000206000820151816000015560208201518160010160006101000a81548160ff02191690831515021790555060408201518160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600201556080820151816003015560a08201518160040160006101000a81548160ff0219169083151502179055509050506004547f370b09ab844737f9ba8d7e02c6bb837b4ecacd3de27024c04e2fc44c1dce65b18383426040516108fe93929190613f6b565b60405180910390a26004600081548092919061091990613fd1565b9190505550610926612c2d565b50505050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613e07565b60405180910390fd5b6109c7612bde565b6000811015610a0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0290614065565b60405180910390fd5b80600381905550610a1a612c2d565b50565b610a25612bde565b600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548110610aa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9d906140d1565b60405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020905060006002811115610b0e57610b0d61376c565b5b8160050160009054906101000a900460ff166002811115610b3257610b3161376c565b5b14610b72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b699061413d565b60405180910390fd5b60025481600301548260010154610b89919061415d565b610b93919061415d565b421015610bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcc906141dd565b60405180910390fd5b6000610be13384612c36565b905080826004018190555060018260050160006101000a81548160ff02191690836002811115610c1457610c1361376c565b5b02179055506000600c6000846002015481526020019081526020016000206000815480929190610c4390613fd1565b9190505590506040518060e001604052808281526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018460000154815260200183815260200142815260200160016002811115610ca657610ca561376c565b5b815250600b60008560020154815260200190815260200160002060008381526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548160ff02191690836002811115610d7557610d7461376c565b5b02179055509050508260000154600a6000856002015481526020019081526020016000206000828254610da891906141fd565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f1b046db135b9e942fdb38793e03af68302b40c7beb83ac18d360774bc94787c984600201548686600001548642604051610e05959493929190614231565b60405180910390a2505050610e18612c2d565b50565b600a6020528060005260406000206000915090505481565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610f0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0690613e07565b60405180910390fd5b610f17612bde565b6000811015610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f52906142d0565b60405180910390fd5b80600281905550610f6a612c2d565b50565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514611000576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ff790613e07565b60405180910390fd5b6004548210611044576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103b9061433c565b60405180910390fd5b806006600084815260200190815260200160002060040160006101000a81548160ff021916908315150217905550817f1ae3e410cf35f6b4cf194bf70854cc944d025b496b9e302625b95b35c1c3a86d82426040516110a492919061435c565b60405180910390a25050565b60606000600c6000868152602001908152602001600020549050600454851061110e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111059061433c565b60405180910390fd5b808410611150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611147906143d1565b60405180910390fd5b600081848661115f919061415d565b11611175578385611170919061415d565b611177565b815b90506000858261118791906141fd565b905060008167ffffffffffffffff8111156111a5576111a46143f1565b5b6040519080825280602002602001820160405280156111de57816020015b6111cb61339a565b8152602001906001900390816111c35790505b50905060005b8281101561131457600b60008a81526020019081526020016000206000828a61120d919061415d565b81526020019081526020016000206040518060e0016040529081600082015481526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820160009054906101000a900460ff1660028111156112d3576112d261376c565b5b60028111156112e5576112e461376c565b5b815250508282815181106112fc576112fb614420565b5b602002602001018190525080806001019150506111e4565b50809450505050509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060008390506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054848661139e919061415d565b116113b45783856113af919061415d565b6113f5565b600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020545b90506000828261140591906141fd565b905060008167ffffffffffffffff811115611423576114226143f1565b5b60405190808252806020026020018201604052801561145c57816020015b6114496133ff565b8152602001906001900390816114415790505b50905060005b828110156117155760008189611478919061415d565b90506000600860008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206040518060c001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900460ff16600281111561152e5761152d61376c565b5b60028111156115405761153f61376c565b5b815250509050600060066000836040015181526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff161515151581525050905060006116228d85612c36565b905060008084606001511161163857600061164d565b8360600151846020015161164c919061415d565b5b90506040518061016001604052808681526020018560000151815260200185602001518152602001828152602001856040015181526020018460600151815260200185606001518152602001846020015115158152602001846040015173ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018560a0015160028111156116e2576116e161376c565b5b8152508787815181106116f8576116f7614420565b5b602002602001018190525050505050508080600101915050611462565b50809450505050509392505050565b60035481565b611732612f32565b61173c6000612fb0565b565b600c6020528060005260406000206000915090505481565b61175e612bde565b8160045481106117a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179a9061433c565b60405180910390fd5b6006600082815260200190815260200160002060040160009054906101000a900460ff16611806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117fd9061449b565b60405180910390fd5b60035482101561184b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184290614507565b60405180910390fd5b6000600660008581526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff16151515158152505090508060200151156119d157823414611963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195a90614573565b60405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050501580156119cb573d6000803e3d6000fd5b50611a68565b60003414611a14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0b906145df565b60405180910390fd5b611a6733600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685846040015173ffffffffffffffffffffffffffffffffffffffff16613074909392919063ffffffff16565b5b6000600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506040518060c00160405280858152602001428152602001868152602001836080015181526020016000815260200160006002811115611aee57611aed61376c565b5b815250600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff02191690836002811115611b9e57611b9d61376c565b5b0217905550905050600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190611bf690613fd1565b919050555083600a60008781526020019081526020016000206000828254611c1e919061415d565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f9cfd25589d1eb8ad71e342a86a8524e83522e3936c0803048c08f6d9ad974f4085878442604051611c7194939291906145ff565b60405180910390a2505050611c84612c2d565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600454905090565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514611d4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d4590613e07565b60405180910390fd5b611d56612bde565b600c6000838152602001908152602001600020548110611dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da290614690565b60405180910390fd5b6004548210611def576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de6906146fc565b60405180910390fd5b6000600b60008481526020019081526020016000206000838152602001908152602001600020905060016002811115611e2b57611e2a61376c565b5b8160060160009054906101000a900460ff166002811115611e4f57611e4e61376c565b5b14611e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8690614768565b60405180910390fd5b6000600860008360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083600201548152602001908152602001600020905060016002811115611f1f57611f1e61376c565b5b8160050160009054906101000a900460ff166002811115611f4357611f4261376c565b5b14611f83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7a90614768565b60405180910390fd5b600060066000836002015481526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250509050600082600401549050600081846000015461206e919061415d565b905060028460050160006101000a81548160ff021916908360028111156120985761209761376c565b5b021790555060028560060160006101000a81548160ff021916908360028111156120c5576120c461376c565b5b02179055508260200151156121875780341015612117576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210e90614573565b60405180910390fd5b8460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612181573d6000803e3d6000fd5b506122e0565b80836040015173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016121c59190613925565b602060405180830381865afa1580156121e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612206919061479d565b1015612247576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223e90614816565b60405180910390fd5b6000341461228a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612281906145df565b60405180910390fd5b6122df338660010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683866040015173ffffffffffffffffffffffffffffffffffffffff16613074909392919063ffffffff16565b5b8460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f367b66f9ceebb8f85f8997340ab1be093eb75f3b70e14f4a849b1633b931281e856002015488844260405161235494939291906145ff565b60405180910390a25050505050612369612c2d565b5050565b606060008267ffffffffffffffff81111561238b5761238a6143f1565b5b6040519080825280602002602001820160405280156123c457816020015b6123b1613483565b8152602001906001900390816123a95790505b50905060008060005b600454811080156123e8575085876123e5919061415d565b83105b15612534576006600082815260200190815260200160002060040160009054906101000a900460ff16156125215786831061251257600660008281526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250508483815181106124f8576124f7614420565b5b6020026020010181905250818061250e90613fd1565b9250505b828061251d90613fd1565b9350505b808061252c90613fd1565b9150506123cd565b5060008167ffffffffffffffff811115612551576125506143f1565b5b60405190808252806020026020018201604052801561258a57816020015b612577613483565b81526020019060019003908161256f5790505b50905060005b828110156125de578481815181106125ab576125aa614420565b5b60200260200101518282815181106125c6576125c5614420565b5b60200260200101819052508080600101915050612590565b508094505050505092915050565b6060600454831115612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262a90614882565b60405180910390fd5b60006004548385612644919061415d565b1161265a578284612655919061415d565b61265e565b6004545b90506000848261266e91906141fd565b905060008167ffffffffffffffff81111561268c5761268b6143f1565b5b6040519080825280602002602001820160405280156126c557816020015b6126b2613483565b8152602001906001900390816126aa5790505b50905060005b828110156127d1576006600082896126e3919061415d565b81526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250508282815181106127b9576127b8614420565b5b602002602001018190525080806001019150506126cb565b5080935050505092915050565b60025481565b6127ec612f32565b6127f4612bde565b80600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612853612c2d565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514612940576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293790613e07565b60405180910390fd5b612948612bde565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129ae906148ee565b60405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612a00612c2d565b50565b612a0b612f32565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7190614980565b60405180910390fd5b612a8381612fb0565b50565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514612b19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b1090613e07565b60405180910390fd5b612b21612bde565b600047905060003373ffffffffffffffffffffffffffffffffffffffff1682604051612b4c906149d1565b60006040518083038185875af1925050503d8060008114612b89576040519150601f19603f3d011682016040523d82523d6000602084013e612b8e565b606091505b5050905080612bd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bc990614a32565b60405180910390fd5b5050612bdc612c2d565b565b600260015403612c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c1a90614a9e565b60405180910390fd5b6002600181905550565b60018081905550565b6000600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548210612cb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb0906140d1565b60405180910390fd5b6000600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206040518060c001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900460ff166002811115612d6d57612d6c61376c565b5b6002811115612d7f57612d7e61376c565b5b81525050905060006002811115612d9957612d9861376c565b5b8160a001516002811115612db057612daf61376c565b5b14612dc2578060800151915050612f2c565b600060066000836040015181526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff16151515158152505090506000826020015142612ea491906141fd565b905060008360600151118015612ebd5750826060015181115b15612eca57826060015190505b6000620f42406301e133806064612ee19190614abe565b612eeb9190614abe565b620f42408385606001518760000151612f049190614abe565b612f0e9190614abe565b612f189190614abe565b612f229190614b2f565b9050809450505050505b92915050565b612f3a6130fd565b73ffffffffffffffffffffffffffffffffffffffff16612f58611c88565b73ffffffffffffffffffffffffffffffffffffffff1614612fae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa590614bac565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6130f7846323b872dd60e01b85858560405160240161309593929190614bcc565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613105565b50505050565b600033905090565b6000613167826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166131cd9092919063ffffffff16565b90506000815114806131895750808060200190518101906131889190614c18565b5b6131c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131bf90614cb7565b60405180910390fd5b505050565b60606131dc84846000856131e5565b90509392505050565b60608247101561322a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161322190614d49565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132539190614dcf565b60006040518083038185875af1925050503d8060008114613290576040519150601f19603f3d011682016040523d82523d6000602084013e613295565b606091505b50915091506132a6878383876132b2565b92505050949350505050565b6060831561331457600083510361330c576132cc85613327565b61330b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330290614e32565b60405180910390fd5b5b82905061331f565b61331e838361334a565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561335d5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133919190614ea7565b60405180910390fd5b6040518060e0016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600060028111156133f9576133f861376c565b5b81525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000600281111561347d5761347c61376c565b5b81525090565b6040518060c0016040528060008152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000151581525090565b600080fd5b60008115159050919050565b6134ed816134d8565b81146134f857600080fd5b50565b60008135905061350a816134e4565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061353b82613510565b9050919050565b61354b81613530565b811461355657600080fd5b50565b60008135905061356881613542565b92915050565b6000819050919050565b6135818161356e565b811461358c57600080fd5b50565b60008135905061359e81613578565b92915050565b600080600080608085870312156135be576135bd6134d3565b5b60006135cc878288016134fb565b94505060206135dd87828801613559565b93505060406135ee8782880161358f565b92505060606135ff8782880161358f565b91505092959194509250565b600060208284031215613621576136206134d3565b5b600061362f8482850161358f565b91505092915050565b6136418161356e565b82525050565b600060208201905061365c6000830184613638565b92915050565b600060208284031215613678576136776134d3565b5b600061368684828501613559565b91505092915050565b600080604083850312156136a6576136a56134d3565b5b60006136b48582860161358f565b92505060206136c5858286016134fb565b9150509250929050565b6000806000606084860312156136e8576136e76134d3565b5b60006136f68682870161358f565b93505060206137078682870161358f565b92505060406137188682870161358f565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137578161356e565b82525050565b61376681613530565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600381106137ac576137ab61376c565b5b50565b60008190506137bd8261379b565b919050565b60006137cd826137af565b9050919050565b6137dd816137c2565b82525050565b60e0820160008201516137f9600085018261374e565b50602082015161380c602085018261375d565b50604082015161381f604085018261374e565b506060820151613832606085018261374e565b506080820151613845608085018261374e565b5060a082015161385860a085018261374e565b5060c082015161386b60c08501826137d4565b50505050565b600061387d83836137e3565b60e08301905092915050565b6000602082019050919050565b60006138a182613722565b6138ab818561372d565b93506138b68361373e565b8060005b838110156138e75781516138ce8882613871565b97506138d983613889565b9250506001810190506138ba565b5085935050505092915050565b6000602082019050818103600083015261390e8184613896565b905092915050565b61391f81613530565b82525050565b600060208201905061393a6000830184613916565b92915050565b600080600060608486031215613959576139586134d3565b5b600061396786828701613559565b93505060206139788682870161358f565b92505060406139898682870161358f565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6139c8816134d8565b82525050565b6000819050919050565b60006139f36139ee6139e984613510565b6139ce565b613510565b9050919050565b6000613a05826139d8565b9050919050565b6000613a17826139fa565b9050919050565b613a2781613a0c565b82525050565b61016082016000820151613a44600085018261374e565b506020820151613a57602085018261374e565b506040820151613a6a604085018261374e565b506060820151613a7d606085018261374e565b506080820151613a90608085018261374e565b5060a0820151613aa360a085018261374e565b5060c0820151613ab660c085018261374e565b5060e0820151613ac960e08501826139bf565b50610100820151613ade610100850182613a1e565b50610120820151613af361012085018261374e565b50610140820151613b086101408501826137d4565b50505050565b6000613b1a8383613a2d565b6101608301905092915050565b6000602082019050919050565b6000613b3f82613993565b613b49818561399e565b9350613b54836139af565b8060005b83811015613b85578151613b6c8882613b0e565b9750613b7783613b27565b925050600181019050613b58565b5085935050505092915050565b60006020820190508181036000830152613bac8184613b34565b905092915050565b60008060408385031215613bcb57613bca6134d3565b5b6000613bd98582860161358f565b9250506020613bea8582860161358f565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60c082016000820151613c36600085018261374e565b506020820151613c4960208501826139bf565b506040820151613c5c6040850182613a1e565b506060820151613c6f606085018261374e565b506080820151613c82608085018261374e565b5060a0820151613c9560a08501826139bf565b50505050565b6000613ca78383613c20565b60c08301905092915050565b6000602082019050919050565b6000613ccb82613bf4565b613cd58185613bff565b9350613ce083613c10565b8060005b83811015613d11578151613cf88882613c9b565b9750613d0383613cb3565b925050600181019050613ce4565b5085935050505092915050565b60006020820190508181036000830152613d388184613cc0565b905092915050565b60008060408385031215613d5757613d566134d3565b5b6000613d6585828601613559565b9250506020613d76858286016134fb565b9150509250929050565b613d89816134d8565b82525050565b6000602082019050613da46000830184613d80565b92915050565b600082825260208201905092915050565b7f4e6f7420616e204d616e61676572000000000000000000000000000000000000600082015250565b6000613df1600e83613daa565b9150613dfc82613dbb565b602082019050919050565b60006020820190508181036000830152613e2081613de4565b9050919050565b7f496e76616c696420746f6b656e00000000000000000000000000000000000000600082015250565b6000613e5d600d83613daa565b9150613e6882613e27565b602082019050919050565b60006020820190508181036000830152613e8c81613e50565b9050919050565b7f415052206d7573742062652067726561746572207468616e2030000000000000600082015250565b6000613ec9601a83613daa565b9150613ed482613e93565b602082019050919050565b60006020820190508181036000830152613ef881613ebc565b9050919050565b7f496e76616c6964204c6f636b204475726174696f6e0000000000000000000000600082015250565b6000613f35601583613daa565b9150613f4082613eff565b602082019050919050565b60006020820190508181036000830152613f6481613f28565b9050919050565b6000606082019050613f806000830186613638565b613f8d6020830185613638565b613f9a6040830184613638565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613fdc8261356e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361400e5761400d613fa2565b5b600182019050919050565b7f496e76616c696420416d6f756e74000000000000000000000000000000000000600082015250565b600061404f600e83613daa565b915061405a82614019565b602082019050919050565b6000602082019050818103600083015261407e81614042565b9050919050565b7f496e76616c6964207374616b6520696e64657800000000000000000000000000600082015250565b60006140bb601383613daa565b91506140c682614085565b602082019050919050565b600060208201905081810360008301526140ea816140ae565b9050919050565b7f5374616b65206e6f742061637469766500000000000000000000000000000000600082015250565b6000614127601083613daa565b9150614132826140f1565b602082019050919050565b600060208201905081810360008301526141568161411a565b9050919050565b60006141688261356e565b91506141738361356e565b925082820190508082111561418b5761418a613fa2565b5b92915050565b7f5374616b65207374696c6c206c6f636b65640000000000000000000000000000600082015250565b60006141c7601283613daa565b91506141d282614191565b602082019050919050565b600060208201905081810360008301526141f6816141ba565b9050919050565b60006142088261356e565b91506142138361356e565b925082820390508181111561422b5761422a613fa2565b5b92915050565b600060a0820190506142466000830188613638565b6142536020830187613638565b6142606040830186613638565b61426d6060830185613638565b61427a6080830184613638565b9695505050505050565b7f496e76616c6964204475726174696f6e00000000000000000000000000000000600082015250565b60006142ba601083613daa565b91506142c582614284565b602082019050919050565b600060208201905081810360008301526142e9816142ad565b9050919050565b7f496e76616c696420706f6f6c2049440000000000000000000000000000000000600082015250565b6000614326600f83613daa565b9150614331826142f0565b602082019050919050565b6000602082019050818103600083015261435581614319565b9050919050565b60006040820190506143716000830185613d80565b61437e6020830184613638565b9392505050565b7f4f6666736574206f7574206f6620626f756e6473000000000000000000000000600082015250565b60006143bb601483613daa565b91506143c682614385565b602082019050919050565b600060208201905081810360008301526143ea816143ae565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b6000614485601283613daa565b91506144908261444f565b602082019050919050565b600060208201905081810360008301526144b481614478565b9050919050565b7f496e76616c6964205374616b6520416d6f756e74000000000000000000000000600082015250565b60006144f1601483613daa565b91506144fc826144bb565b602082019050919050565b60006020820190508181036000830152614520816144e4565b9050919050565b7f496e636f727265637420414d4520616d6f756e74000000000000000000000000600082015250565b600061455d601483613daa565b915061456882614527565b602082019050919050565b6000602082019050818103600083015261458c81614550565b9050919050565b7f4e6f20414d45206e656564656400000000000000000000000000000000000000600082015250565b60006145c9600d83613daa565b91506145d482614593565b602082019050919050565b600060208201905081810360008301526145f8816145bc565b9050919050565b60006080820190506146146000830187613638565b6146216020830186613638565b61462e6040830185613638565b61463b6060830184613638565b95945050505050565b7f496e76616c6964205374616b6520496e64657800000000000000000000000000600082015250565b600061467a601383613daa565b915061468582614644565b602082019050919050565b600060208201905081810360008301526146a98161466d565b9050919050565b7f496e76616c696420506f6f6c20496e6465780000000000000000000000000000600082015250565b60006146e6601283613daa565b91506146f1826146b0565b602082019050919050565b60006020820190508181036000830152614715816146d9565b9050919050565b7f52657175657374206e6f742070656e64696e6700000000000000000000000000600082015250565b6000614752601383613daa565b915061475d8261471c565b602082019050919050565b6000602082019050818103600083015261478181614745565b9050919050565b60008151905061479781613578565b92915050565b6000602082840312156147b3576147b26134d3565b5b60006147c184828501614788565b91505092915050565b7f496e73756666696369656e7420746f6b656e2062616c616e6365000000000000600082015250565b6000614800601a83613daa565b915061480b826147ca565b602082019050919050565b6000602082019050818103600083015261482f816147f3565b9050919050565b7f496e76616c6964204f6666736574000000000000000000000000000000000000600082015250565b600061486c600e83613daa565b915061487782614836565b602082019050919050565b6000602082019050818103600083015261489b8161485f565b9050919050565b7f496e76616c696420747265617375727920616464726573730000000000000000600082015250565b60006148d8601883613daa565b91506148e3826148a2565b602082019050919050565b60006020820190508181036000830152614907816148cb565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061496a602683613daa565b91506149758261490e565b604082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b600081905092915050565b50565b60006149bb6000836149a0565b91506149c6826149ab565b600082019050919050565b60006149dc826149ae565b9150819050919050565b7f4661696c656420746f2073656e64204f5a4f7300000000000000000000000000600082015250565b6000614a1c601383613daa565b9150614a27826149e6565b602082019050919050565b60006020820190508181036000830152614a4b81614a0f565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614a88601f83613daa565b9150614a9382614a52565b602082019050919050565b60006020820190508181036000830152614ab781614a7b565b9050919050565b6000614ac98261356e565b9150614ad48361356e565b9250828202614ae28161356e565b91508282048414831517614af957614af8613fa2565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614b3a8261356e565b9150614b458361356e565b925082614b5557614b54614b00565b5b828204905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614b96602083613daa565b9150614ba182614b60565b602082019050919050565b60006020820190508181036000830152614bc581614b89565b9050919050565b6000606082019050614be16000830186613916565b614bee6020830185613916565b614bfb6040830184613638565b949350505050565b600081519050614c12816134e4565b92915050565b600060208284031215614c2e57614c2d6134d3565b5b6000614c3c84828501614c03565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614ca1602a83613daa565b9150614cac82614c45565b604082019050919050565b60006020820190508181036000830152614cd081614c94565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614d33602683613daa565b9150614d3e82614cd7565b604082019050919050565b60006020820190508181036000830152614d6281614d26565b9050919050565b600081519050919050565b60005b83811015614d92578082015181840152602081019050614d77565b60008484015250505050565b6000614da982614d69565b614db381856149a0565b9350614dc3818560208601614d74565b80840191505092915050565b6000614ddb8284614d9e565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e1c601d83613daa565b9150614e2782614de6565b602082019050919050565b60006020820190508181036000830152614e4b81614e0f565b9050919050565b600081519050919050565b6000601f19601f8301169050919050565b6000614e7982614e52565b614e838185613daa565b9350614e93818560208601614d74565b614e9c81614e5d565b840191505092915050565b60006020820190508181036000830152614ec18184614e6e565b90509291505056fea264697066735822122066a35cd672fe2661e2b7007d97a12a4d1aa95e69aa972e1cdedb239cf537aa9a64736f6c63430008160033
Deployed ByteCode
0x6080604052600436106101665760003560e01c8063722b4b32116100d1578063a7753f091161008a578063c9b8981711610064578063c9b8981714610532578063f0f442601461056f578063f2fde38b14610598578063fcb67c5b146105c157610166565b8063a7753f09146104a1578063a8bd7300146104de578063b8f49d8f1461050957610166565b8063722b4b32146103995780637b0472f0146103d65780638da5cb5b146103f25780638eec5d701461041d5780639433773014610448578063969d68581461046457610166565b8063560e878311610123578063560e878314610289578063603edf55146102b257806361d027b3146102ef5780636a6c8d8b1461031a5780636b036f4514610357578063715018a61461038257610166565b80630bc313a61461016b5780630d29fcd41461019457806323095721146101bd57806324df6bee146101e657806338864e2114610223578063392cb1c214610260575b600080fd5b34801561017757600080fd5b50610192600480360381019061018d91906135a4565b6105d8565b005b3480156101a057600080fd5b506101bb60048036038101906101b6919061360b565b61092c565b005b3480156101c957600080fd5b506101e460048036038101906101df919061360b565b610a1d565b005b3480156101f257600080fd5b5061020d6004803603810190610208919061360b565b610e1b565b60405161021a9190613647565b60405180910390f35b34801561022f57600080fd5b5061024a60048036038101906102459190613662565b610e33565b6040516102579190613647565b60405180910390f35b34801561026c57600080fd5b506102876004803603810190610282919061360b565b610e7c565b005b34801561029557600080fd5b506102b060048036038101906102ab919061368f565b610f6d565b005b3480156102be57600080fd5b506102d960048036038101906102d491906136cf565b6110b0565b6040516102e691906138f4565b60405180910390f35b3480156102fb57600080fd5b50610304611323565b6040516103119190613925565b60405180910390f35b34801561032657600080fd5b50610341600480360381019061033c9190613940565b611349565b60405161034e9190613b92565b60405180910390f35b34801561036357600080fd5b5061036c611724565b6040516103799190613647565b60405180910390f35b34801561038e57600080fd5b5061039761172a565b005b3480156103a557600080fd5b506103c060048036038101906103bb919061360b565b61173e565b6040516103cd9190613647565b60405180910390f35b6103f060048036038101906103eb9190613bb4565b611756565b005b3480156103fe57600080fd5b50610407611c88565b6040516104149190613925565b60405180910390f35b34801561042957600080fd5b50610432611cb1565b60405161043f9190613647565b60405180910390f35b610462600480360381019061045d9190613bb4565b611cbb565b005b34801561047057600080fd5b5061048b60048036038101906104869190613bb4565b61236d565b6040516104989190613d1e565b60405180910390f35b3480156104ad57600080fd5b506104c860048036038101906104c39190613bb4565b6125ec565b6040516104d59190613d1e565b60405180910390f35b3480156104ea57600080fd5b506104f36127de565b6040516105009190613647565b60405180910390f35b34801561051557600080fd5b50610530600480360381019061052b9190613d40565b6127e4565b005b34801561053e57600080fd5b5061055960048036038101906105549190613662565b612857565b6040516105669190613d8f565b60405180910390f35b34801561057b57600080fd5b5061059660048036038101906105919190613662565b6128ad565b005b3480156105a457600080fd5b506105bf60048036038101906105ba9190613662565b612a03565b005b3480156105cd57600080fd5b506105d6612a86565b005b6105e0612bde565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066a90613e07565b60405180910390fd5b8380156106ac5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b806106ee5750831580156106ed5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b5b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072490613e73565b60405180910390fd5b60008211610770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076790613edf565b60405180910390fd5b6000811480610782575062093a808110155b6107c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b890613f4b565b60405180910390fd5b6040518060c00160405280600454815260200185151581526020018473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001600115158152506006600060045481526020019081526020016000206000820151816000015560208201518160010160006101000a81548160ff02191690831515021790555060408201518160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600201556080820151816003015560a08201518160040160006101000a81548160ff0219169083151502179055509050506004547f370b09ab844737f9ba8d7e02c6bb837b4ecacd3de27024c04e2fc44c1dce65b18383426040516108fe93929190613f6b565b60405180910390a26004600081548092919061091990613fd1565b9190505550610926612c2d565b50505050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613e07565b60405180910390fd5b6109c7612bde565b6000811015610a0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0290614065565b60405180910390fd5b80600381905550610a1a612c2d565b50565b610a25612bde565b600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548110610aa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9d906140d1565b60405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020905060006002811115610b0e57610b0d61376c565b5b8160050160009054906101000a900460ff166002811115610b3257610b3161376c565b5b14610b72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b699061413d565b60405180910390fd5b60025481600301548260010154610b89919061415d565b610b93919061415d565b421015610bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcc906141dd565b60405180910390fd5b6000610be13384612c36565b905080826004018190555060018260050160006101000a81548160ff02191690836002811115610c1457610c1361376c565b5b02179055506000600c6000846002015481526020019081526020016000206000815480929190610c4390613fd1565b9190505590506040518060e001604052808281526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018460000154815260200183815260200142815260200160016002811115610ca657610ca561376c565b5b815250600b60008560020154815260200190815260200160002060008381526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548160ff02191690836002811115610d7557610d7461376c565b5b02179055509050508260000154600a6000856002015481526020019081526020016000206000828254610da891906141fd565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f1b046db135b9e942fdb38793e03af68302b40c7beb83ac18d360774bc94787c984600201548686600001548642604051610e05959493929190614231565b60405180910390a2505050610e18612c2d565b50565b600a6020528060005260406000206000915090505481565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610f0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0690613e07565b60405180910390fd5b610f17612bde565b6000811015610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f52906142d0565b60405180910390fd5b80600281905550610f6a612c2d565b50565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514611000576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ff790613e07565b60405180910390fd5b6004548210611044576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103b9061433c565b60405180910390fd5b806006600084815260200190815260200160002060040160006101000a81548160ff021916908315150217905550817f1ae3e410cf35f6b4cf194bf70854cc944d025b496b9e302625b95b35c1c3a86d82426040516110a492919061435c565b60405180910390a25050565b60606000600c6000868152602001908152602001600020549050600454851061110e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111059061433c565b60405180910390fd5b808410611150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611147906143d1565b60405180910390fd5b600081848661115f919061415d565b11611175578385611170919061415d565b611177565b815b90506000858261118791906141fd565b905060008167ffffffffffffffff8111156111a5576111a46143f1565b5b6040519080825280602002602001820160405280156111de57816020015b6111cb61339a565b8152602001906001900390816111c35790505b50905060005b8281101561131457600b60008a81526020019081526020016000206000828a61120d919061415d565b81526020019081526020016000206040518060e0016040529081600082015481526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820160009054906101000a900460ff1660028111156112d3576112d261376c565b5b60028111156112e5576112e461376c565b5b815250508282815181106112fc576112fb614420565b5b602002602001018190525080806001019150506111e4565b50809450505050509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060008390506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054848661139e919061415d565b116113b45783856113af919061415d565b6113f5565b600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020545b90506000828261140591906141fd565b905060008167ffffffffffffffff811115611423576114226143f1565b5b60405190808252806020026020018201604052801561145c57816020015b6114496133ff565b8152602001906001900390816114415790505b50905060005b828110156117155760008189611478919061415d565b90506000600860008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206040518060c001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900460ff16600281111561152e5761152d61376c565b5b60028111156115405761153f61376c565b5b815250509050600060066000836040015181526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff161515151581525050905060006116228d85612c36565b905060008084606001511161163857600061164d565b8360600151846020015161164c919061415d565b5b90506040518061016001604052808681526020018560000151815260200185602001518152602001828152602001856040015181526020018460600151815260200185606001518152602001846020015115158152602001846040015173ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018560a0015160028111156116e2576116e161376c565b5b8152508787815181106116f8576116f7614420565b5b602002602001018190525050505050508080600101915050611462565b50809450505050509392505050565b60035481565b611732612f32565b61173c6000612fb0565b565b600c6020528060005260406000206000915090505481565b61175e612bde565b8160045481106117a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179a9061433c565b60405180910390fd5b6006600082815260200190815260200160002060040160009054906101000a900460ff16611806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117fd9061449b565b60405180910390fd5b60035482101561184b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184290614507565b60405180910390fd5b6000600660008581526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff16151515158152505090508060200151156119d157823414611963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195a90614573565b60405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050501580156119cb573d6000803e3d6000fd5b50611a68565b60003414611a14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0b906145df565b60405180910390fd5b611a6733600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685846040015173ffffffffffffffffffffffffffffffffffffffff16613074909392919063ffffffff16565b5b6000600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506040518060c00160405280858152602001428152602001868152602001836080015181526020016000815260200160006002811115611aee57611aed61376c565b5b815250600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff02191690836002811115611b9e57611b9d61376c565b5b0217905550905050600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190611bf690613fd1565b919050555083600a60008781526020019081526020016000206000828254611c1e919061415d565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f9cfd25589d1eb8ad71e342a86a8524e83522e3936c0803048c08f6d9ad974f4085878442604051611c7194939291906145ff565b60405180910390a2505050611c84612c2d565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600454905090565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514611d4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d4590613e07565b60405180910390fd5b611d56612bde565b600c6000838152602001908152602001600020548110611dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da290614690565b60405180910390fd5b6004548210611def576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de6906146fc565b60405180910390fd5b6000600b60008481526020019081526020016000206000838152602001908152602001600020905060016002811115611e2b57611e2a61376c565b5b8160060160009054906101000a900460ff166002811115611e4f57611e4e61376c565b5b14611e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8690614768565b60405180910390fd5b6000600860008360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083600201548152602001908152602001600020905060016002811115611f1f57611f1e61376c565b5b8160050160009054906101000a900460ff166002811115611f4357611f4261376c565b5b14611f83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7a90614768565b60405180910390fd5b600060066000836002015481526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250509050600082600401549050600081846000015461206e919061415d565b905060028460050160006101000a81548160ff021916908360028111156120985761209761376c565b5b021790555060028560060160006101000a81548160ff021916908360028111156120c5576120c461376c565b5b02179055508260200151156121875780341015612117576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210e90614573565b60405180910390fd5b8460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612181573d6000803e3d6000fd5b506122e0565b80836040015173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016121c59190613925565b602060405180830381865afa1580156121e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612206919061479d565b1015612247576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223e90614816565b60405180910390fd5b6000341461228a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612281906145df565b60405180910390fd5b6122df338660010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683866040015173ffffffffffffffffffffffffffffffffffffffff16613074909392919063ffffffff16565b5b8460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f367b66f9ceebb8f85f8997340ab1be093eb75f3b70e14f4a849b1633b931281e856002015488844260405161235494939291906145ff565b60405180910390a25050505050612369612c2d565b5050565b606060008267ffffffffffffffff81111561238b5761238a6143f1565b5b6040519080825280602002602001820160405280156123c457816020015b6123b1613483565b8152602001906001900390816123a95790505b50905060008060005b600454811080156123e8575085876123e5919061415d565b83105b15612534576006600082815260200190815260200160002060040160009054906101000a900460ff16156125215786831061251257600660008281526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250508483815181106124f8576124f7614420565b5b6020026020010181905250818061250e90613fd1565b9250505b828061251d90613fd1565b9350505b808061252c90613fd1565b9150506123cd565b5060008167ffffffffffffffff811115612551576125506143f1565b5b60405190808252806020026020018201604052801561258a57816020015b612577613483565b81526020019060019003908161256f5790505b50905060005b828110156125de578481815181106125ab576125aa614420565b5b60200260200101518282815181106125c6576125c5614420565b5b60200260200101819052508080600101915050612590565b508094505050505092915050565b6060600454831115612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262a90614882565b60405180910390fd5b60006004548385612644919061415d565b1161265a578284612655919061415d565b61265e565b6004545b90506000848261266e91906141fd565b905060008167ffffffffffffffff81111561268c5761268b6143f1565b5b6040519080825280602002602001820160405280156126c557816020015b6126b2613483565b8152602001906001900390816126aa5790505b50905060005b828110156127d1576006600082896126e3919061415d565b81526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1615151515815250508282815181106127b9576127b8614420565b5b602002602001018190525080806001019150506126cb565b5080935050505092915050565b60025481565b6127ec612f32565b6127f4612bde565b80600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612853612c2d565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514612940576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293790613e07565b60405180910390fd5b612948612bde565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129ae906148ee565b60405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612a00612c2d565b50565b612a0b612f32565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7190614980565b60405180910390fd5b612a8381612fb0565b50565b60011515600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514612b19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b1090613e07565b60405180910390fd5b612b21612bde565b600047905060003373ffffffffffffffffffffffffffffffffffffffff1682604051612b4c906149d1565b60006040518083038185875af1925050503d8060008114612b89576040519150601f19603f3d011682016040523d82523d6000602084013e612b8e565b606091505b5050905080612bd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bc990614a32565b60405180910390fd5b5050612bdc612c2d565b565b600260015403612c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c1a90614a9e565b60405180910390fd5b6002600181905550565b60018081905550565b6000600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548210612cb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb0906140d1565b60405180910390fd5b6000600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206040518060c001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900460ff166002811115612d6d57612d6c61376c565b5b6002811115612d7f57612d7e61376c565b5b81525050905060006002811115612d9957612d9861376c565b5b8160a001516002811115612db057612daf61376c565b5b14612dc2578060800151915050612f2c565b600060066000836040015181526020019081526020016000206040518060c0016040529081600082015481526020016001820160009054906101000a900460ff161515151581526020016001820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff16151515158152505090506000826020015142612ea491906141fd565b905060008360600151118015612ebd5750826060015181115b15612eca57826060015190505b6000620f42406301e133806064612ee19190614abe565b612eeb9190614abe565b620f42408385606001518760000151612f049190614abe565b612f0e9190614abe565b612f189190614abe565b612f229190614b2f565b9050809450505050505b92915050565b612f3a6130fd565b73ffffffffffffffffffffffffffffffffffffffff16612f58611c88565b73ffffffffffffffffffffffffffffffffffffffff1614612fae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa590614bac565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6130f7846323b872dd60e01b85858560405160240161309593929190614bcc565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613105565b50505050565b600033905090565b6000613167826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166131cd9092919063ffffffff16565b90506000815114806131895750808060200190518101906131889190614c18565b5b6131c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131bf90614cb7565b60405180910390fd5b505050565b60606131dc84846000856131e5565b90509392505050565b60608247101561322a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161322190614d49565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132539190614dcf565b60006040518083038185875af1925050503d8060008114613290576040519150601f19603f3d011682016040523d82523d6000602084013e613295565b606091505b50915091506132a6878383876132b2565b92505050949350505050565b6060831561331457600083510361330c576132cc85613327565b61330b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330290614e32565b60405180910390fd5b5b82905061331f565b61331e838361334a565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561335d5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133919190614ea7565b60405180910390fd5b6040518060e0016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600060028111156133f9576133f861376c565b5b81525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000600281111561347d5761347c61376c565b5b81525090565b6040518060c0016040528060008152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000151581525090565b600080fd5b60008115159050919050565b6134ed816134d8565b81146134f857600080fd5b50565b60008135905061350a816134e4565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061353b82613510565b9050919050565b61354b81613530565b811461355657600080fd5b50565b60008135905061356881613542565b92915050565b6000819050919050565b6135818161356e565b811461358c57600080fd5b50565b60008135905061359e81613578565b92915050565b600080600080608085870312156135be576135bd6134d3565b5b60006135cc878288016134fb565b94505060206135dd87828801613559565b93505060406135ee8782880161358f565b92505060606135ff8782880161358f565b91505092959194509250565b600060208284031215613621576136206134d3565b5b600061362f8482850161358f565b91505092915050565b6136418161356e565b82525050565b600060208201905061365c6000830184613638565b92915050565b600060208284031215613678576136776134d3565b5b600061368684828501613559565b91505092915050565b600080604083850312156136a6576136a56134d3565b5b60006136b48582860161358f565b92505060206136c5858286016134fb565b9150509250929050565b6000806000606084860312156136e8576136e76134d3565b5b60006136f68682870161358f565b93505060206137078682870161358f565b92505060406137188682870161358f565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137578161356e565b82525050565b61376681613530565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600381106137ac576137ab61376c565b5b50565b60008190506137bd8261379b565b919050565b60006137cd826137af565b9050919050565b6137dd816137c2565b82525050565b60e0820160008201516137f9600085018261374e565b50602082015161380c602085018261375d565b50604082015161381f604085018261374e565b506060820151613832606085018261374e565b506080820151613845608085018261374e565b5060a082015161385860a085018261374e565b5060c082015161386b60c08501826137d4565b50505050565b600061387d83836137e3565b60e08301905092915050565b6000602082019050919050565b60006138a182613722565b6138ab818561372d565b93506138b68361373e565b8060005b838110156138e75781516138ce8882613871565b97506138d983613889565b9250506001810190506138ba565b5085935050505092915050565b6000602082019050818103600083015261390e8184613896565b905092915050565b61391f81613530565b82525050565b600060208201905061393a6000830184613916565b92915050565b600080600060608486031215613959576139586134d3565b5b600061396786828701613559565b93505060206139788682870161358f565b92505060406139898682870161358f565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6139c8816134d8565b82525050565b6000819050919050565b60006139f36139ee6139e984613510565b6139ce565b613510565b9050919050565b6000613a05826139d8565b9050919050565b6000613a17826139fa565b9050919050565b613a2781613a0c565b82525050565b61016082016000820151613a44600085018261374e565b506020820151613a57602085018261374e565b506040820151613a6a604085018261374e565b506060820151613a7d606085018261374e565b506080820151613a90608085018261374e565b5060a0820151613aa360a085018261374e565b5060c0820151613ab660c085018261374e565b5060e0820151613ac960e08501826139bf565b50610100820151613ade610100850182613a1e565b50610120820151613af361012085018261374e565b50610140820151613b086101408501826137d4565b50505050565b6000613b1a8383613a2d565b6101608301905092915050565b6000602082019050919050565b6000613b3f82613993565b613b49818561399e565b9350613b54836139af565b8060005b83811015613b85578151613b6c8882613b0e565b9750613b7783613b27565b925050600181019050613b58565b5085935050505092915050565b60006020820190508181036000830152613bac8184613b34565b905092915050565b60008060408385031215613bcb57613bca6134d3565b5b6000613bd98582860161358f565b9250506020613bea8582860161358f565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60c082016000820151613c36600085018261374e565b506020820151613c4960208501826139bf565b506040820151613c5c6040850182613a1e565b506060820151613c6f606085018261374e565b506080820151613c82608085018261374e565b5060a0820151613c9560a08501826139bf565b50505050565b6000613ca78383613c20565b60c08301905092915050565b6000602082019050919050565b6000613ccb82613bf4565b613cd58185613bff565b9350613ce083613c10565b8060005b83811015613d11578151613cf88882613c9b565b9750613d0383613cb3565b925050600181019050613ce4565b5085935050505092915050565b60006020820190508181036000830152613d388184613cc0565b905092915050565b60008060408385031215613d5757613d566134d3565b5b6000613d6585828601613559565b9250506020613d76858286016134fb565b9150509250929050565b613d89816134d8565b82525050565b6000602082019050613da46000830184613d80565b92915050565b600082825260208201905092915050565b7f4e6f7420616e204d616e61676572000000000000000000000000000000000000600082015250565b6000613df1600e83613daa565b9150613dfc82613dbb565b602082019050919050565b60006020820190508181036000830152613e2081613de4565b9050919050565b7f496e76616c696420746f6b656e00000000000000000000000000000000000000600082015250565b6000613e5d600d83613daa565b9150613e6882613e27565b602082019050919050565b60006020820190508181036000830152613e8c81613e50565b9050919050565b7f415052206d7573742062652067726561746572207468616e2030000000000000600082015250565b6000613ec9601a83613daa565b9150613ed482613e93565b602082019050919050565b60006020820190508181036000830152613ef881613ebc565b9050919050565b7f496e76616c6964204c6f636b204475726174696f6e0000000000000000000000600082015250565b6000613f35601583613daa565b9150613f4082613eff565b602082019050919050565b60006020820190508181036000830152613f6481613f28565b9050919050565b6000606082019050613f806000830186613638565b613f8d6020830185613638565b613f9a6040830184613638565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613fdc8261356e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361400e5761400d613fa2565b5b600182019050919050565b7f496e76616c696420416d6f756e74000000000000000000000000000000000000600082015250565b600061404f600e83613daa565b915061405a82614019565b602082019050919050565b6000602082019050818103600083015261407e81614042565b9050919050565b7f496e76616c6964207374616b6520696e64657800000000000000000000000000600082015250565b60006140bb601383613daa565b91506140c682614085565b602082019050919050565b600060208201905081810360008301526140ea816140ae565b9050919050565b7f5374616b65206e6f742061637469766500000000000000000000000000000000600082015250565b6000614127601083613daa565b9150614132826140f1565b602082019050919050565b600060208201905081810360008301526141568161411a565b9050919050565b60006141688261356e565b91506141738361356e565b925082820190508082111561418b5761418a613fa2565b5b92915050565b7f5374616b65207374696c6c206c6f636b65640000000000000000000000000000600082015250565b60006141c7601283613daa565b91506141d282614191565b602082019050919050565b600060208201905081810360008301526141f6816141ba565b9050919050565b60006142088261356e565b91506142138361356e565b925082820390508181111561422b5761422a613fa2565b5b92915050565b600060a0820190506142466000830188613638565b6142536020830187613638565b6142606040830186613638565b61426d6060830185613638565b61427a6080830184613638565b9695505050505050565b7f496e76616c6964204475726174696f6e00000000000000000000000000000000600082015250565b60006142ba601083613daa565b91506142c582614284565b602082019050919050565b600060208201905081810360008301526142e9816142ad565b9050919050565b7f496e76616c696420706f6f6c2049440000000000000000000000000000000000600082015250565b6000614326600f83613daa565b9150614331826142f0565b602082019050919050565b6000602082019050818103600083015261435581614319565b9050919050565b60006040820190506143716000830185613d80565b61437e6020830184613638565b9392505050565b7f4f6666736574206f7574206f6620626f756e6473000000000000000000000000600082015250565b60006143bb601483613daa565b91506143c682614385565b602082019050919050565b600060208201905081810360008301526143ea816143ae565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b6000614485601283613daa565b91506144908261444f565b602082019050919050565b600060208201905081810360008301526144b481614478565b9050919050565b7f496e76616c6964205374616b6520416d6f756e74000000000000000000000000600082015250565b60006144f1601483613daa565b91506144fc826144bb565b602082019050919050565b60006020820190508181036000830152614520816144e4565b9050919050565b7f496e636f727265637420414d4520616d6f756e74000000000000000000000000600082015250565b600061455d601483613daa565b915061456882614527565b602082019050919050565b6000602082019050818103600083015261458c81614550565b9050919050565b7f4e6f20414d45206e656564656400000000000000000000000000000000000000600082015250565b60006145c9600d83613daa565b91506145d482614593565b602082019050919050565b600060208201905081810360008301526145f8816145bc565b9050919050565b60006080820190506146146000830187613638565b6146216020830186613638565b61462e6040830185613638565b61463b6060830184613638565b95945050505050565b7f496e76616c6964205374616b6520496e64657800000000000000000000000000600082015250565b600061467a601383613daa565b915061468582614644565b602082019050919050565b600060208201905081810360008301526146a98161466d565b9050919050565b7f496e76616c696420506f6f6c20496e6465780000000000000000000000000000600082015250565b60006146e6601283613daa565b91506146f1826146b0565b602082019050919050565b60006020820190508181036000830152614715816146d9565b9050919050565b7f52657175657374206e6f742070656e64696e6700000000000000000000000000600082015250565b6000614752601383613daa565b915061475d8261471c565b602082019050919050565b6000602082019050818103600083015261478181614745565b9050919050565b60008151905061479781613578565b92915050565b6000602082840312156147b3576147b26134d3565b5b60006147c184828501614788565b91505092915050565b7f496e73756666696369656e7420746f6b656e2062616c616e6365000000000000600082015250565b6000614800601a83613daa565b915061480b826147ca565b602082019050919050565b6000602082019050818103600083015261482f816147f3565b9050919050565b7f496e76616c6964204f6666736574000000000000000000000000000000000000600082015250565b600061486c600e83613daa565b915061487782614836565b602082019050919050565b6000602082019050818103600083015261489b8161485f565b9050919050565b7f496e76616c696420747265617375727920616464726573730000000000000000600082015250565b60006148d8601883613daa565b91506148e3826148a2565b602082019050919050565b60006020820190508181036000830152614907816148cb565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061496a602683613daa565b91506149758261490e565b604082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b600081905092915050565b50565b60006149bb6000836149a0565b91506149c6826149ab565b600082019050919050565b60006149dc826149ae565b9150819050919050565b7f4661696c656420746f2073656e64204f5a4f7300000000000000000000000000600082015250565b6000614a1c601383613daa565b9150614a27826149e6565b602082019050919050565b60006020820190508181036000830152614a4b81614a0f565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614a88601f83613daa565b9150614a9382614a52565b602082019050919050565b60006020820190508181036000830152614ab781614a7b565b9050919050565b6000614ac98261356e565b9150614ad48361356e565b9250828202614ae28161356e565b91508282048414831517614af957614af8613fa2565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614b3a8261356e565b9150614b458361356e565b925082614b5557614b54614b00565b5b828204905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614b96602083613daa565b9150614ba182614b60565b602082019050919050565b60006020820190508181036000830152614bc581614b89565b9050919050565b6000606082019050614be16000830186613916565b614bee6020830185613916565b614bfb6040830184613638565b949350505050565b600081519050614c12816134e4565b92915050565b600060208284031215614c2e57614c2d6134d3565b5b6000614c3c84828501614c03565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614ca1602a83613daa565b9150614cac82614c45565b604082019050919050565b60006020820190508181036000830152614cd081614c94565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614d33602683613daa565b9150614d3e82614cd7565b604082019050919050565b60006020820190508181036000830152614d6281614d26565b9050919050565b600081519050919050565b60005b83811015614d92578082015181840152602081019050614d77565b60008484015250505050565b6000614da982614d69565b614db381856149a0565b9350614dc3818560208601614d74565b80840191505092915050565b6000614ddb8284614d9e565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e1c601d83613daa565b9150614e2782614de6565b602082019050919050565b60006020820190508181036000830152614e4b81614e0f565b9050919050565b600081519050919050565b6000601f19601f8301169050919050565b6000614e7982614e52565b614e838185613daa565b9350614e93818560208601614d74565b614e9c81614e5d565b840191505092915050565b60006020820190508181036000830152614ec18184614e6e565b90509291505056fea264697066735822122066a35cd672fe2661e2b7007d97a12a4d1aa95e69aa972e1cdedb239cf537aa9a64736f6c63430008160033