More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 298 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Stake | 21120985 | 13 days ago | IN | 0 ETH | 0.00050091 | ||||
Claim Rewards | 21117458 | 13 days ago | IN | 0 ETH | 9.44350406 | ||||
Stake | 21117453 | 13 days ago | IN | 0 ETH | 0.00135029 | ||||
Stake | 21099794 | 16 days ago | IN | 0 ETH | 0.00041953 | ||||
Claim Rewards | 21099765 | 16 days ago | IN | 0 ETH | 0.00043748 | ||||
Claim Rewards | 20988279 | 31 days ago | IN | 0 ETH | 0.00142397 | ||||
Claim Rewards | 20880567 | 46 days ago | IN | 0 ETH | 0.00133582 | ||||
Claim Rewards | 20875326 | 47 days ago | IN | 0 ETH | 0.00094704 | ||||
Stake | 20872520 | 47 days ago | IN | 0 ETH | 0.00214643 | ||||
Claim Rewards | 20872512 | 47 days ago | IN | 0 ETH | 0.00196632 | ||||
Stake | 20812005 | 56 days ago | IN | 0 ETH | 0.00243073 | ||||
Stake | 20795726 | 58 days ago | IN | 0 ETH | 0.00132049 | ||||
Stake | 20700973 | 71 days ago | IN | 0 ETH | 0.0007287 | ||||
Stake | 20700967 | 71 days ago | IN | 0 ETH | 0.00083897 | ||||
Stake | 20696353 | 72 days ago | IN | 0 ETH | 0.00027008 | ||||
Stake | 20665126 | 76 days ago | IN | 0 ETH | 0.00074894 | ||||
Claim Rewards | 20658250 | 77 days ago | IN | 0 ETH | 0.00025824 | ||||
Stake | 20614193 | 83 days ago | IN | 0 ETH | 0.00018235 | ||||
Withdraw | 20614130 | 83 days ago | IN | 0 ETH | 0.00027915 | ||||
Claim Rewards | 20614123 | 83 days ago | IN | 0 ETH | 0.00020533 | ||||
Stake | 20606723 | 84 days ago | IN | 0 ETH | 0.00029197 | ||||
Claim Rewards | 20603334 | 85 days ago | IN | 0 ETH | 0.00026639 | ||||
Claim Rewards | 20603294 | 85 days ago | IN | 0 ETH | 0.00025021 | ||||
Stake | 20600632 | 85 days ago | IN | 0 ETH | 0.00039511 | ||||
Withdraw | 20566775 | 90 days ago | IN | 0 ETH | 0.00058225 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LatticeFixedRewardStaking
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /** * @title Lattice Fixed Reward Staking Contract * @author Stardust Collective <[email protected]> * * Transformed idea from SushiSwap's https://github.com/sushiswap/StakingContract */ pragma solidity ^0.8.18; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {ReentrancyGuard} from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import {Pausable} from '@openzeppelin/contracts/security/Pausable.sol'; import {AccessControl} from '@openzeppelin/contracts/access/AccessControl.sol'; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; contract LatticeFixedRewardStaking is ReentrancyGuard, Pausable, AccessControl { using SafeERC20 for IERC20; bytes32 public constant CONFIGURATION_ROLE = keccak256('CONFIGURATION_ROLE'); bytes32 public constant STEWARD_ROLE = keccak256('STEWARD_ROLE'); uint256 public constant MAGNITUDE_CONSTANT = 1e40; IERC20 public immutable stakingToken; uint256 public minStakingAmount; IERC20 public immutable rewardToken; uint256 public minRewardAmount; uint64 public immutable programStartsAt; uint256 public programStakedLiquidity; uint256 public programRewardRemaining; uint256 public programRewardPerLiquidity; uint256 public programRewardLost; uint256 public programRewardLostWithdrawn; uint64 public programRewardsDepletionAt; uint64 public programLastAccruedRewardsAt; uint256 public taxRatioNumerator; uint256 public taxRatioDenominator; uint256 public taxAccumulated; uint256 public taxAccumulatedWithdrawn; struct StakingUser { uint256 amountStaked; uint256 lastProgramRewardPerLiquidity; } mapping(address => StakingUser) public users; event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardsClaimed( address indexed user, uint256 rewardsTaxed, uint256 taxes ); event StakingConditionChanged( uint256 remainingRewards, uint64 programLastAccruedRewardsAt, uint64 programRewardsDepletionAt ); event StakingRestrictionChanged( uint256 minStakingAmount, uint256 minRewardAmount ); event TaxConditionChanged( uint256 taxRatioNumerator, uint256 taxRatioDenominator ); event RewardsLost(uint256 amount); event RecoveredERC20(address indexed token, uint256 amount); constructor( address _stakingToken, uint256 _minStakingAmount, address _rewardToken, uint256 _minRewardAmount, uint64 _programStartsAt, uint64 _programRewardsDepletionAt, uint256 _taxRatioNumerator, uint256 _taxRatioDenominator, address[] memory managers ) { require( _programStartsAt < _programRewardsDepletionAt, 'Invalid program timeline' ); require(_stakingToken != address(0), 'Invalid staking token'); require(_rewardToken != address(0), 'Invalid reward token'); require( _taxRatioNumerator * 10 <= _taxRatioDenominator, 'Tax ratio exceeds 10% cap' ); // Program Condition stakingToken = IERC20(_stakingToken); minStakingAmount = _minStakingAmount; rewardToken = IERC20(_rewardToken); minRewardAmount = _minRewardAmount; // Program Timeline programStartsAt = _programStartsAt; programRewardsDepletionAt = _programRewardsDepletionAt; programLastAccruedRewardsAt = _programStartsAt; // Program Taxes taxRatioNumerator = _taxRatioNumerator; taxRatioDenominator = _taxRatioDenominator; _setRoleAdmin(CONFIGURATION_ROLE, CONFIGURATION_ROLE); _setRoleAdmin(STEWARD_ROLE, CONFIGURATION_ROLE); _grantRole(CONFIGURATION_ROLE, _msgSender()); _grantRole(STEWARD_ROLE, _msgSender()); for (uint16 i = 0; i < managers.length; i++) { _grantRole(STEWARD_ROLE, managers[i]); } } /** * General Functions */ function stake( uint256 _amount, bool _claimExistingRewards ) external nonReentrant whenNotPaused { _stake(_amount, _claimExistingRewards); } function withdraw( uint256 _amount, bool _claimExistingRewards, bool _waiveExistingRewards ) external nonReentrant whenNotPaused { _withdraw(_amount, _claimExistingRewards, _waiveExistingRewards); } function claimRewards() external nonReentrant whenNotPaused { // We generate a new rewards period to include immediately previous rewards for the user _accrueRewardsPeriod(); _claimRewards(false); } /** * Calculate a new rewards period for the current time, and calculate rewards based * on the next program reward per liquidity. */ function availableRewards( address user ) external view returns (uint256 _userRewardsTaxed, uint256 _userTaxes) { uint64 _programNextAccruedRewardsAt = uint64( Math.min(block.timestamp, programRewardsDepletionAt) ); uint64 _rewardRemainingDuration = programRewardsDepletionAt - programLastAccruedRewardsAt; uint64 _rewardPeriodDuration = _programNextAccruedRewardsAt - programLastAccruedRewardsAt; uint256 _rewardAmountForPeriod = 0; if (_rewardRemainingDuration > 0) { _rewardAmountForPeriod = Math.mulDiv( programRewardRemaining, _rewardPeriodDuration, _rewardRemainingDuration ); } uint256 _nextProgramRewardPerLiquidity = programRewardPerLiquidity; // Use actual RPL if the program has ended or staked liquidity == 0 if ( _programNextAccruedRewardsAt <= programRewardsDepletionAt && programStakedLiquidity > 0 ) { _nextProgramRewardPerLiquidity += Math.mulDiv( _rewardAmountForPeriod, MAGNITUDE_CONSTANT, programStakedLiquidity ); } (_userRewardsTaxed, _userTaxes) = _calculateRewardsAndTaxes( users[user].lastProgramRewardPerLiquidity, users[user].amountStaked, _nextProgramRewardPerLiquidity, taxRatioNumerator, taxRatioDenominator ); } /** * General Internal Functions */ function _stake(uint256 _amount, bool _claimExistingRewards) internal { require( block.timestamp >= programStartsAt, 'Staking program not open yet' ); require( programRewardRemaining > 0, 'There are no rewards deposited yet' ); require( block.timestamp < programRewardsDepletionAt, 'Staking program has closed' ); require(_amount > 0, 'Unable to stake 0 tokens'); require( _amount + users[_msgSender()].amountStaked >= minStakingAmount, 'Staking less than required by the specified program' ); stakingToken.safeTransferFrom(_msgSender(), address(this), _amount); // Generate a new rewards period => new program reward per liquidity _accrueRewardsPeriod(); uint256 _userNextAmountStaked = users[_msgSender()].amountStaked + _amount; if (_claimExistingRewards) { _claimRewards(false); } else { _saveRewards(_userNextAmountStaked); } users[_msgSender()].amountStaked = _userNextAmountStaked; programStakedLiquidity += _amount; emit Staked(_msgSender(), _amount); } function _withdraw( uint256 _amount, bool _claimExistingRewards, bool _waiveExistingRewards ) internal { require(users[_msgSender()].amountStaked != 0, 'No amount to withdraw'); require( users[_msgSender()].amountStaked >= _amount, 'Amount to withdraw is greater than staked' ); require(_amount > 0, 'Unable to withdraw 0 tokens'); require( users[_msgSender()].amountStaked == _amount || users[_msgSender()].amountStaked - _amount >= minStakingAmount, 'The final staked amount would be less than required by the specified program' ); // Generate a new rewards period => new program reward per liquidity _accrueRewardsPeriod(); uint256 _userNextAmountStaked = users[_msgSender()].amountStaked - _amount; if (_claimExistingRewards || _userNextAmountStaked == 0) { _claimRewards(_waiveExistingRewards); } else { _saveRewards(_userNextAmountStaked); } users[_msgSender()].amountStaked = _userNextAmountStaked; programStakedLiquidity -= _amount; stakingToken.safeTransfer(_msgSender(), _amount); emit Withdrawn(_msgSender(), _amount); } function _claimRewards(bool _waiveExistingRewards) internal { ( uint256 _userRewardsTaxed, uint256 _userTaxes ) = _calculateRewardsAndTaxes( users[_msgSender()].lastProgramRewardPerLiquidity, users[_msgSender()].amountStaked, programRewardPerLiquidity, taxRatioNumerator, taxRatioDenominator ); require( _userRewardsTaxed >= minRewardAmount || _waiveExistingRewards, 'Not enough rewards to claim' ); users[_msgSender()] .lastProgramRewardPerLiquidity = programRewardPerLiquidity; if (_waiveExistingRewards) { programRewardLost += _userRewardsTaxed + _userTaxes; emit RewardsLost(_userRewardsTaxed + _userTaxes); } else { taxAccumulated += _userTaxes; rewardToken.safeTransfer(_msgSender(), _userRewardsTaxed); emit RewardsClaimed(_msgSender(), _userRewardsTaxed, _userTaxes); } } /** * We derive a new [user].lastProgramRewardPerLiquidity based on the new amount * staked and considering previous rewards. The in the next call to _calculateRewardsAndTaxes() * user will receive both previous-non-claimed rewards and new rewards. */ function _saveRewards(uint256 _nextAmountStaked) internal { ( uint256 _userRewardsTaxed, uint256 _userTaxes ) = _calculateRewardsAndTaxes( users[_msgSender()].lastProgramRewardPerLiquidity, users[_msgSender()].amountStaked, programRewardPerLiquidity, taxRatioNumerator, taxRatioDenominator ); uint256 _userRewards = _userRewardsTaxed + _userTaxes; uint256 _userProgramRewardPerLiquidityDelta = Math.mulDiv( _userRewards, MAGNITUDE_CONSTANT, _nextAmountStaked ); users[_msgSender()].lastProgramRewardPerLiquidity = programRewardPerLiquidity - _userProgramRewardPerLiquidityDelta; } /** * Generate a new rewards period, discard unused/reserved reward amount for the generated period * add reward per liquidity for the generated period in order to claim/calculate rewards. */ function _accrueRewardsPeriod() internal { uint64 _programNextAccruedRewardsAt = uint64( Math.min(block.timestamp, programRewardsDepletionAt) ); uint64 _rewardRemainingDuration = programRewardsDepletionAt - programLastAccruedRewardsAt; // Don't accrue if the remaining duration is 0 (program has ended) if (_rewardRemainingDuration == 0) { return; } uint64 _rewardPeriodDuration = _programNextAccruedRewardsAt - programLastAccruedRewardsAt; uint256 _rewardAmountForPeriod = Math.mulDiv( programRewardRemaining, _rewardPeriodDuration, _rewardRemainingDuration ); uint256 _programRewardPerLiquidityChange = 0; if (programStakedLiquidity > 0) { _programRewardPerLiquidityChange = Math.mulDiv( _rewardAmountForPeriod, MAGNITUDE_CONSTANT, programStakedLiquidity ); programRewardPerLiquidity += _programRewardPerLiquidityChange; } else { programRewardLost += _rewardAmountForPeriod; emit RewardsLost(_rewardAmountForPeriod); } programRewardRemaining -= _rewardAmountForPeriod; programLastAccruedRewardsAt = _programNextAccruedRewardsAt; } function _calculateRewardsAndTaxes( uint256 _userLastProgramRewardPerLiquidity, uint256 _userAmountStaked, uint256 _programRewardPerLiquidity, uint256 _taxRatioNumerator, uint256 _taxRatioDenominator ) internal pure returns (uint256 _userRewardsTaxed, uint256 _userTaxes) { uint256 _userProgramRewardPerLiquidityDelta = _programRewardPerLiquidity - _userLastProgramRewardPerLiquidity; uint256 _userRewards = Math.mulDiv( _userProgramRewardPerLiquidityDelta, _userAmountStaked, MAGNITUDE_CONSTANT ); _userTaxes = Math.mulDiv( _userRewards, _taxRatioNumerator, _taxRatioDenominator ); _userRewardsTaxed = _userRewards - _userTaxes; } /** * Admin Functions */ function accrueRewardsPeriod() external onlyRole(STEWARD_ROLE) { require( block.timestamp >= programStartsAt, 'Staking program not open yet' ); _accrueRewardsPeriod(); } function depositProgramRewards( uint256 _amount ) external nonReentrant onlyRole(STEWARD_ROLE) { require(_amount > 0, 'Unable to deposit 0 reward tokens'); rewardToken.safeTransferFrom(_msgSender(), address(this), _amount); programRewardRemaining += _amount; emit StakingConditionChanged( programRewardRemaining, programLastAccruedRewardsAt, programRewardsDepletionAt ); } function withdrawProgramRewards( uint256 _amount ) external nonReentrant onlyRole(STEWARD_ROLE) { require(_amount > 0, 'Unable to withdraw 0 reward tokens'); require( _amount <= programRewardRemaining, 'Unable to withdraw more than the program reward remaining' ); programRewardRemaining -= _amount; rewardToken.safeTransfer(_msgSender(), _amount); emit StakingConditionChanged( programRewardRemaining, programLastAccruedRewardsAt, programRewardsDepletionAt ); } function withdrawProgramLostRewards( uint256 _amount ) external nonReentrant onlyRole(STEWARD_ROLE) { require(_amount > 0, 'Unable to withdraw 0 lost rewards tokens'); uint256 _lostRewardsAvailable = programRewardLost - programRewardLostWithdrawn; require( _amount <= _lostRewardsAvailable, 'Amount is greater than available lost rewards' ); programRewardLostWithdrawn += _amount; rewardToken.safeTransfer(_msgSender(), _amount); } function withdrawProgramTaxes( uint256 _amount ) external nonReentrant onlyRole(CONFIGURATION_ROLE) { require(_amount > 0, 'Unable to withdraw 0 program taxes'); uint256 _taxesAvailable = taxAccumulated - taxAccumulatedWithdrawn; require( _amount <= _taxesAvailable, 'Amount is greater than available taxes' ); taxAccumulatedWithdrawn += _amount; rewardToken.safeTransfer(_msgSender(), _amount); } function updateProgramDepletionDate( uint64 _programRewardsDepletionAt ) external onlyRole(STEWARD_ROLE) { require( _programRewardsDepletionAt > block.timestamp, 'New program depletion date must be greater than current time' ); programRewardsDepletionAt = _programRewardsDepletionAt; emit StakingConditionChanged( programRewardRemaining, programLastAccruedRewardsAt, programRewardsDepletionAt ); } function updateProgramRestriction( uint256 _minStakingAmount, uint256 _minRewardAmount ) external onlyRole(STEWARD_ROLE) { minStakingAmount = _minStakingAmount; minRewardAmount = _minRewardAmount; emit StakingRestrictionChanged(minStakingAmount, minRewardAmount); } function updateProgramTax( uint256 _taxRatioNumerator, uint256 _taxRatioDenominator ) external onlyRole(CONFIGURATION_ROLE) { require( _taxRatioNumerator * 10 <= _taxRatioDenominator, 'Tax ratio exceeds 10% cap' ); taxRatioNumerator = _taxRatioNumerator; taxRatioDenominator = _taxRatioDenominator; emit TaxConditionChanged(taxRatioNumerator, taxRatioDenominator); } function recoverERC20( IERC20 token, uint256 amount ) external nonReentrant onlyRole(STEWARD_ROLE) { require( address(token) != address(stakingToken), 'Cannot withdraw the staking token' ); require( address(token) != address(rewardToken), 'Cannot withdraw the reward token' ); uint256 tokenBalance = token.balanceOf(address(this)); require(tokenBalance >= amount, 'Not enough tokens to withdraw'); token.safeTransfer(_msgSender(), amount); emit RecoveredERC20(address(token), amount); } function pause() external onlyRole(STEWARD_ROLE) { _pause(); } function unpause() external onlyRole(STEWARD_ROLE) { _unpause(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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. */ 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]. */ 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } 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"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return 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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"uint256","name":"_minStakingAmount","type":"uint256"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_minRewardAmount","type":"uint256"},{"internalType":"uint64","name":"_programStartsAt","type":"uint64"},{"internalType":"uint64","name":"_programRewardsDepletionAt","type":"uint64"},{"internalType":"uint256","name":"_taxRatioNumerator","type":"uint256"},{"internalType":"uint256","name":"_taxRatioDenominator","type":"uint256"},{"internalType":"address[]","name":"managers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RecoveredERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsTaxed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"taxes","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsLost","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"remainingRewards","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"programLastAccruedRewardsAt","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"programRewardsDepletionAt","type":"uint64"}],"name":"StakingConditionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minStakingAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minRewardAmount","type":"uint256"}],"name":"StakingRestrictionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"taxRatioNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"taxRatioDenominator","type":"uint256"}],"name":"TaxConditionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"CONFIGURATION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAGNITUDE_CONSTANT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STEWARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrueRewardsPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"availableRewards","outputs":[{"internalType":"uint256","name":"_userRewardsTaxed","type":"uint256"},{"internalType":"uint256","name":"_userTaxes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositProgramRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minStakingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programLastAccruedRewardsAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programRewardLost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programRewardLostWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programRewardPerLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programRewardRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programRewardsDepletionAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programStakedLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"programStartsAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_claimExistingRewards","type":"bool"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxAccumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxAccumulatedWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxRatioDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxRatioNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_programRewardsDepletionAt","type":"uint64"}],"name":"updateProgramDepletionDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minStakingAmount","type":"uint256"},{"internalType":"uint256","name":"_minRewardAmount","type":"uint256"}],"name":"updateProgramRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taxRatioNumerator","type":"uint256"},{"internalType":"uint256","name":"_taxRatioDenominator","type":"uint256"}],"name":"updateProgramTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint256","name":"amountStaked","type":"uint256"},{"internalType":"uint256","name":"lastProgramRewardPerLiquidity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_claimExistingRewards","type":"bool"},{"internalType":"bool","name":"_waiveExistingRewards","type":"bool"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawProgramLostRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawProgramRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawProgramTaxes","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162005828380380620058288339818101604052810190620000379190620008c4565b60016000819055506000600160006101000a81548160ff0219169083151502179055508367ffffffffffffffff168567ffffffffffffffff1610620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000a23565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff160362000125576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200011c9062000a95565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362000197576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200018e9062000b07565b60405180910390fd5b81600a84620001a7919062000b58565b1115620001eb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001e29062000bf3565b60405180910390fd5b8873ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050876003819055508673ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050856004819055508467ffffffffffffffff1660c08167ffffffffffffffff168152505083600a60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555084600a60086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555082600b8190555081600c819055506200030f7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef476806200046d60201b60201c565b620003617fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef4766200046d60201b60201c565b620003a27f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef47662000396620004d160201b60201c565b620004d960201b60201c565b620003e37fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec620003d7620004d160201b60201c565b620004d960201b60201c565b60005b81518161ffff1610156200045d57620004477fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec838361ffff168151811062000433576200043262000c15565b5b6020026020010151620004d960201b60201c565b8080620004549062000c52565b915050620003e6565b5050505050505050505062000c81565b60006200048083620005cb60201b60201c565b90508160026000858152602001908152602001600020600101819055508181847fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff60405160405180910390a4505050565b600033905090565b620004eb8282620005eb60201b60201c565b620005c75760016002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506200056c620004d160201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600060026000838152602001908152602001600020600101549050919050565b60006002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000697826200066a565b9050919050565b620006a9816200068a565b8114620006b557600080fd5b50565b600081519050620006c9816200069e565b92915050565b6000819050919050565b620006e481620006cf565b8114620006f057600080fd5b50565b6000815190506200070481620006d9565b92915050565b600067ffffffffffffffff82169050919050565b62000729816200070a565b81146200073557600080fd5b50565b60008151905062000749816200071e565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200079f8262000754565b810181811067ffffffffffffffff82111715620007c157620007c062000765565b5b80604052505050565b6000620007d662000656565b9050620007e4828262000794565b919050565b600067ffffffffffffffff82111562000807576200080662000765565b5b602082029050602081019050919050565b600080fd5b6000620008346200082e84620007e9565b620007ca565b905080838252602082019050602084028301858111156200085a576200085962000818565b5b835b81811015620008875780620008728882620006b8565b8452602084019350506020810190506200085c565b5050509392505050565b600082601f830112620008a957620008a86200074f565b5b8151620008bb8482602086016200081d565b91505092915050565b60008060008060008060008060006101208a8c031215620008ea57620008e962000660565b5b6000620008fa8c828d01620006b8565b99505060206200090d8c828d01620006f3565b9850506040620009208c828d01620006b8565b9750506060620009338c828d01620006f3565b9650506080620009468c828d0162000738565b95505060a0620009598c828d0162000738565b94505060c06200096c8c828d01620006f3565b93505060e06200097f8c828d01620006f3565b9250506101008a015167ffffffffffffffff811115620009a457620009a362000665565b5b620009b28c828d0162000891565b9150509295985092959850929598565b600082825260208201905092915050565b7f496e76616c69642070726f6772616d2074696d656c696e650000000000000000600082015250565b600062000a0b601883620009c2565b915062000a1882620009d3565b602082019050919050565b6000602082019050818103600083015262000a3e81620009fc565b9050919050565b7f496e76616c6964207374616b696e6720746f6b656e0000000000000000000000600082015250565b600062000a7d601583620009c2565b915062000a8a8262000a45565b602082019050919050565b6000602082019050818103600083015262000ab08162000a6e565b9050919050565b7f496e76616c69642072657761726420746f6b656e000000000000000000000000600082015250565b600062000aef601483620009c2565b915062000afc8262000ab7565b602082019050919050565b6000602082019050818103600083015262000b228162000ae0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000b6582620006cf565b915062000b7283620006cf565b925082820262000b8281620006cf565b9150828204841483151762000b9c5762000b9b62000b29565b5b5092915050565b7f54617820726174696f2065786365656473203130252063617000000000000000600082015250565b600062000bdb601983620009c2565b915062000be88262000ba3565b602082019050919050565b6000602082019050818103600083015262000c0e8162000bcc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061ffff82169050919050565b600062000c5f8262000c44565b915061ffff820362000c765762000c7562000b29565b5b600182019050919050565b60805160a05160c051614b2a62000cfe600039600081816112d1015281816114b9015261256201526000818161087a01528181610cd50152818161103d01528181611181015281816113d4015281816115720152611f8f015260008181610b9001528181610c47015281816124c1015261275f0152614b2a6000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c806381014fe411610151578063abe50f19116100c3578063cdf24c2f11610087578063cdf24c2f146106a7578063d37e51da146106c5578063d547741f146106e3578063f7c618c1146106ff578063f854a27f1461071d578063fb9604ce1461074e57610269565b8063abe50f1914610629578063b12ed45e14610645578063bd5c566414610663578063c4b8d27d14610681578063c9e721aa1461069d57610269565b8063a217fddf11610115578063a217fddf14610568578063a728517614610586578063a7c8a9e6146105a2578063a87430ba146105be578063a9170d81146105ef578063aa8172301461060d57610269565b806381014fe4146104d85780638456cb59146104f65780638980f11f1461050057806391d148541461051c57806392930b451461054c57610269565b806336568abe116101ea5780635c975abb116101ae5780635c975abb14610424578063643059161461044257806372f702f3146104605780637718d1e21461047e5780637f91d2351461049c5780638021e4a2146104ba57610269565b806336568abe146103ba578063372500ab146103d65780633f4ba83a146103e057806348928d57146103ea5780635992c85c1461040857610269565b8063230f289711610231578063230f289714610314578063248a9ca31461033257806325c065b1146103625780632876d7e4146103805780632f2ff15d1461039e57610269565b806301ffc9a71461026e57806306e0cf651461029e5780630f8cc3fd146102bc57806312d3b8c9146102da57806316992873146102f8575b600080fd5b61028860048036038101906102839190613199565b61076a565b60405161029591906131e1565b60405180910390f35b6102a66107e4565b6040516102b39190613215565b60405180910390f35b6102c46107ea565b6040516102d19190613215565b60405180910390f35b6102e26107f0565b6040516102ef9190613215565b60405180910390f35b610312600480360381019061030d919061325c565b6107f6565b005b61031c61094d565b6040516103299190613215565b60405180910390f35b61034c600480360381019061034791906132bf565b610953565b60405161035991906132fb565b60405180910390f35b61036a610973565b6040516103779190613215565b60405180910390f35b610388610979565b6040516103959190613215565b60405180910390f35b6103b860048036038101906103b39190613374565b61097f565b005b6103d460048036038101906103cf9190613374565b6109a0565b005b6103de610a23565b005b6103e8610a4f565b005b6103f2610a84565b6040516103ff9190613215565b60405180910390f35b610422600480360381019061041d91906133b4565b610a8a565b005b61042c610b53565b60405161043991906131e1565b60405180910390f35b61044a610b6a565b60405161045791906132fb565b60405180910390f35b610468610b8e565b6040516104759190613453565b60405180910390f35b610486610bb2565b6040516104939190613215565b60405180910390f35b6104a4610bb8565b6040516104b19190613215565b60405180910390f35b6104c2610bbe565b6040516104cf9190613491565b60405180910390f35b6104e0610bd8565b6040516104ed9190613215565b60405180910390f35b6104fe610bde565b005b61051a600480360381019061051591906134ea565b610c13565b005b61053660048036038101906105319190613374565b610eb0565b60405161054391906131e1565b60405180910390f35b61056660048036038101906105619190613556565b610f1b565b005b610570610f43565b60405161057d91906132fb565b60405180910390f35b6105a0600480360381019061059b919061325c565b610f4a565b005b6105bc60048036038101906105b7919061325c565b61108e565b005b6105d860048036038101906105d391906135a9565b6111d2565b6040516105e69291906135d6565b60405180910390f35b6105f76111f6565b6040516106049190613215565b60405180910390f35b610627600480360381019061062291906133b4565b61120b565b005b610643600480360381019061063e91906135ff565b611285565b005b61064d6112ab565b60405161065a91906132fb565b60405180910390f35b61066b6112cf565b6040516106789190613491565b60405180910390f35b61069b6004803603810190610696919061325c565b6112f3565b005b6106a561148d565b005b6106af61152f565b6040516106bc9190613215565b60405180910390f35b6106cd611535565b6040516106da9190613491565b60405180910390f35b6106fd60048036038101906106f89190613374565b61154f565b005b610707611570565b6040516107149190613453565b60405180910390f35b610737600480360381019061073291906135a9565b611594565b6040516107459291906135d6565b60405180910390f35b6107686004803603810190610763919061366b565b61177a565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107dd57506107dc82611886565b5b9050919050565b60055481565b60085481565b60045481565b6107fe6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6108288161193f565b6000821161086b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108629061371b565b60405180910390fd5b6108bf610876611953565b30847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661195b909392919063ffffffff16565b81600660008282546108d1919061376a565b925050819055507fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166040516109399392919061379e565b60405180910390a15061094a6119e4565b50565b60065481565b600060026000838152602001908152602001600020600101549050919050565b60035481565b60075481565b61098882610953565b6109918161193f565b61099b83836119ee565b505050565b6109a8611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0c90613847565b60405180910390fd5b610a1f8282611acf565b5050565b610a2b6118f0565b610a33611bb1565b610a3b611bfb565b610a456000611dae565b610a4d6119e4565b565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610a798161193f565b610a81612030565b50565b600d5481565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef476610ab48161193f565b81600a84610ac29190613867565b1115610b03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afa906138f5565b60405180910390fd5b82600b8190555081600c819055507f091392e521f32b928e7effd1b5ff766e8c6faf01f5aceb57f54dc32cd2f57583600b54600c54604051610b469291906135d6565b60405180910390a1505050565b6000600160009054906101000a900460ff16905090565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec81565b7f000000000000000000000000000000000000000000000000000000000000000081565b600c5481565b600e5481565b600a60089054906101000a900467ffffffffffffffff1681565b600b5481565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610c088161193f565b610c10612093565b50565b610c1b6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610c458161193f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610cd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cca90613987565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610d61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d58906139f3565b60405180910390fd5b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d9c9190613a22565b602060405180830381865afa158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddd9190613a52565b905082811015610e22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1990613acb565b60405180910390fd5b610e54610e2d611953565b848673ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff167f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b184604051610e9a9190613215565b60405180910390a25050610eac6119e4565b5050565b60006002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b610f236118f0565b610f2b611bb1565b610f3683838361217b565b610f3e6119e4565b505050565b6000801b81565b610f526118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610f7c8161193f565b60008211610fbf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb690613b5d565b60405180910390fd5b6000600954600854610fd19190613b7d565b905080831115611016576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100d90613c23565b60405180910390fd5b8260096000828254611028919061376a565b9250508190555061108161103a611953565b847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b505061108b6119e4565b50565b6110966118f0565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef4766110c08161193f565b60008211611103576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110fa90613cb5565b60405180910390fd5b6000600e54600d546111159190613b7d565b90508083111561115a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115190613d47565b60405180910390fd5b82600e600082825461116c919061376a565b925050819055506111c561117e611953565b847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b50506111cf6119e4565b50565b600f6020528060005260406000206000915090508060000154908060010154905082565b701d6329f1c35ca4bfabb9f561000000000081565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6112358161193f565b82600381905550816004819055507f14207e149af257f57a5573a804ff84d3f14a60673e606ec6c2acdd9f70c355226003546004546040516112789291906135d6565b60405180910390a1505050565b61128d6118f0565b611295611bb1565b61129f8282612560565b6112a76119e4565b5050565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef47681565b7f000000000000000000000000000000000000000000000000000000000000000081565b6112fb6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6113258161193f565b60008211611368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f90613dd9565b60405180910390fd5b6006548211156113ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a490613e6b565b60405180910390fd5b81600660008282546113bf9190613b7d565b925050819055506114186113d1611953565b837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b7fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166040516114799392919061379e565b60405180910390a15061148a6119e4565b50565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6114b78161193f565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16421015611524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151b90613ed7565b60405180910390fd5b61152c611bfb565b50565b60095481565b600a60009054906101000a900467ffffffffffffffff1681565b61155882610953565b6115618161193f565b61156b8383611acf565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006115c342600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff166128e5565b90506000600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166115ff9190613ef7565b90506000600a60089054906101000a900467ffffffffffffffff16836116259190613ef7565b90506000808367ffffffffffffffff16111561165f5761165c6006548367ffffffffffffffff168567ffffffffffffffff166128fe565b90505b60006007549050600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff168567ffffffffffffffff16111580156116a257506000600554115b156116d3576116c582701d6329f1c35ca4bfabb9f56100000000006005546128fe565b816116d0919061376a565b90505b611768600f60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015483600b54600c546129d9565b80975081985050505050505050915091565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6117a48161193f565b428267ffffffffffffffff16116117f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e790613fa5565b60405180910390fd5b81600a60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff1660405161187a9392919061379e565b60405180910390a15050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600260005403611935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192c90614011565b60405180910390fd5b6002600081905550565b6119508161194b611953565b612a33565b50565b600033905090565b6119de846323b872dd60e01b85858560405160240161197c93929190614031565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612ab8565b50505050565b6001600081905550565b6119f88282610eb0565b611acb5760016002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611a70611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b611ad98282610eb0565b15611bad5760006002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b52611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611bb9610b53565b15611bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf0906140b4565b60405180910390fd5b565b6000611c2742600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff166128e5565b90506000600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff16611c639190613ef7565b905060008167ffffffffffffffff1603611c7e575050611dac565b6000600a60089054906101000a900467ffffffffffffffff1683611ca29190613ef7565b90506000611cc76006548367ffffffffffffffff168567ffffffffffffffff166128fe565b90506000806005541115611d1357611cf382701d6329f1c35ca4bfabb9f56100000000006005546128fe565b90508060076000828254611d07919061376a565b92505081905550611d64565b8160086000828254611d25919061376a565b925050819055507fa641ca195988b20fb3185bbfd64521b79089ad0913255a52c171bac83783bdda82604051611d5b9190613215565b60405180910390a15b8160066000828254611d769190613b7d565b9250508190555084600a60086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050505b565b600080611e56600f6000611dc0611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f6000611e0a611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154600754600b54600c546129d9565b9150915060045482101580611e685750825b611ea7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9e90614120565b60405180910390fd5b600754600f6000611eb6611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055508215611f68578082611f09919061376a565b60086000828254611f1a919061376a565b925050819055507fa641ca195988b20fb3185bbfd64521b79089ad0913255a52c171bac83783bdda8183611f4e919061376a565b604051611f5b9190613215565b60405180910390a161202b565b80600d6000828254611f7a919061376a565b92505081905550611fd3611f8c611953565b837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b611fdb611953565b73ffffffffffffffffffffffffffffffffffffffff167fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e32583836040516120229291906135d6565b60405180910390a25b505050565b612038612b7f565b6000600160006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61207c611953565b6040516120899190613a22565b60405180910390a1565b61209b611bb1565b60018060006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120de611953565b6040516120eb9190613a22565b60405180910390a1565b6121768363a9059cbb60e01b8484604051602401612114929190614140565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612ab8565b505050565b6000600f6000612189611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403612207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fe906141b5565b60405180910390fd5b82600f6000612214611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541015612293576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228a90614247565b60405180910390fd5b600083116122d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122cd906142b3565b60405180910390fd5b82600f60006122e3611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541480612383575060035483600f6000612338611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546123809190613b7d565b10155b6123c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b99061436b565b60405180910390fd5b6123ca611bfb565b600083600f60006123d9611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546124219190613b7d565b9050828061242f5750600081145b156124425761243d82611dae565b61244c565b61244b81612bc8565b5b80600f6000612459611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555083600560008282546124ac9190613b7d565b925050819055506125056124be611953565b857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b61250d611953565b73ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5856040516125529190613215565b60405180910390a250505050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff164210156125cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125c490613ed7565b60405180910390fd5b600060065411612612576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612609906143fd565b60405180910390fd5b600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff164210612674576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266b90614469565b60405180910390fd5b600082116126b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126ae906144d5565b60405180910390fd5b600354600f60006126c6611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001548361270f919061376a565b1015612750576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161274790614567565b60405180910390fd5b6127a461275b611953565b30847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661195b909392919063ffffffff16565b6127ac611bfb565b600082600f60006127bb611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154612803919061376a565b9050811561281a576128156000611dae565b612824565b61282381612bc8565b5b80600f6000612831611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055508260056000828254612884919061376a565b92505081905550612893611953565b73ffffffffffffffffffffffffffffffffffffffff167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d846040516128d89190613215565b60405180910390a2505050565b60008183106128f457816128f6565b825b905092915050565b60008060008019858709858702925082811083820303915050600081036129395783828161292f5761292e614587565b5b04925050506129d2565b80841161294557600080fd5b60008486880990508281118203915080830392506000600186190186169050808604955080840493506001818260000304019050808302841793506000600287600302189050808702600203810290508087026002038102905080870260020381029050808702600203810290508087026002038102905080870260020381029050808502955050505050505b9392505050565b600080600087866129ea9190613b7d565b90506000612a0a8289701d6329f1c35ca4bfabb9f56100000000006128fe565b9050612a178187876128fe565b92508281612a259190613b7d565b935050509550959350505050565b612a3d8282610eb0565b612ab457612a4a81612d06565b612a588360001c6020612d33565b604051602001612a699291906146bf565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aab9190614743565b60405180910390fd5b5050565b6000612b1a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612f6f9092919063ffffffff16565b9050600081511115612b7a5780806020019051810190612b3a919061477a565b612b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b7090614819565b60405180910390fd5b5b505050565b612b87610b53565b612bc6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bbd90614885565b60405180910390fd5b565b600080612c70600f6000612bda611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f6000612c24611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154600754600b54600c546129d9565b9150915060008183612c82919061376a565b90506000612ca282701d6329f1c35ca4bfabb9f5610000000000876128fe565b905080600754612cb29190613b7d565b600f6000612cbe611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055505050505050565b6060612d2c8273ffffffffffffffffffffffffffffffffffffffff16601460ff16612d33565b9050919050565b606060006002836002612d469190613867565b612d50919061376a565b67ffffffffffffffff811115612d6957612d686148a5565b5b6040519080825280601f01601f191660200182016040528015612d9b5781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612dd357612dd26148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612e3757612e366148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002612e779190613867565b612e81919061376a565b90505b6001811115612f21577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612ec357612ec26148d4565b5b1a60f81b828281518110612eda57612ed96148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612f1a90614903565b9050612e84565b5060008414612f65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5c90614978565b60405180910390fd5b8091505092915050565b6060612f7e8484600085612f87565b90509392505050565b606082471015612fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fc390614a0a565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612ff59190614a71565b60006040518083038185875af1925050503d8060008114613032576040519150601f19603f3d011682016040523d82523d6000602084013e613037565b606091505b509150915061304887838387613054565b92505050949350505050565b606083156130b65760008351036130ae5761306e856130c9565b6130ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a490614ad4565b60405180910390fd5b5b8290506130c1565b6130c083836130ec565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000825111156130ff5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131339190614743565b60405180910390fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61317681613141565b811461318157600080fd5b50565b6000813590506131938161316d565b92915050565b6000602082840312156131af576131ae61313c565b5b60006131bd84828501613184565b91505092915050565b60008115159050919050565b6131db816131c6565b82525050565b60006020820190506131f660008301846131d2565b92915050565b6000819050919050565b61320f816131fc565b82525050565b600060208201905061322a6000830184613206565b92915050565b613239816131fc565b811461324457600080fd5b50565b60008135905061325681613230565b92915050565b6000602082840312156132725761327161313c565b5b600061328084828501613247565b91505092915050565b6000819050919050565b61329c81613289565b81146132a757600080fd5b50565b6000813590506132b981613293565b92915050565b6000602082840312156132d5576132d461313c565b5b60006132e3848285016132aa565b91505092915050565b6132f581613289565b82525050565b600060208201905061331060008301846132ec565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061334182613316565b9050919050565b61335181613336565b811461335c57600080fd5b50565b60008135905061336e81613348565b92915050565b6000806040838503121561338b5761338a61313c565b5b6000613399858286016132aa565b92505060206133aa8582860161335f565b9150509250929050565b600080604083850312156133cb576133ca61313c565b5b60006133d985828601613247565b92505060206133ea85828601613247565b9150509250929050565b6000819050919050565b600061341961341461340f84613316565b6133f4565b613316565b9050919050565b600061342b826133fe565b9050919050565b600061343d82613420565b9050919050565b61344d81613432565b82525050565b60006020820190506134686000830184613444565b92915050565b600067ffffffffffffffff82169050919050565b61348b8161346e565b82525050565b60006020820190506134a66000830184613482565b92915050565b60006134b782613336565b9050919050565b6134c7816134ac565b81146134d257600080fd5b50565b6000813590506134e4816134be565b92915050565b600080604083850312156135015761350061313c565b5b600061350f858286016134d5565b925050602061352085828601613247565b9150509250929050565b613533816131c6565b811461353e57600080fd5b50565b6000813590506135508161352a565b92915050565b60008060006060848603121561356f5761356e61313c565b5b600061357d86828701613247565b935050602061358e86828701613541565b925050604061359f86828701613541565b9150509250925092565b6000602082840312156135bf576135be61313c565b5b60006135cd8482850161335f565b91505092915050565b60006040820190506135eb6000830185613206565b6135f86020830184613206565b9392505050565b600080604083850312156136165761361561313c565b5b600061362485828601613247565b925050602061363585828601613541565b9150509250929050565b6136488161346e565b811461365357600080fd5b50565b6000813590506136658161363f565b92915050565b6000602082840312156136815761368061313c565b5b600061368f84828501613656565b91505092915050565b600082825260208201905092915050565b7f556e61626c6520746f206465706f73697420302072657761726420746f6b656e60008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000613705602183613698565b9150613710826136a9565b604082019050919050565b60006020820190508181036000830152613734816136f8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613775826131fc565b9150613780836131fc565b92508282019050808211156137985761379761373b565b5b92915050565b60006060820190506137b36000830186613206565b6137c06020830185613482565b6137cd6040830184613482565b949350505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000613831602f83613698565b915061383c826137d5565b604082019050919050565b6000602082019050818103600083015261386081613824565b9050919050565b6000613872826131fc565b915061387d836131fc565b925082820261388b816131fc565b915082820484148315176138a2576138a161373b565b5b5092915050565b7f54617820726174696f2065786365656473203130252063617000000000000000600082015250565b60006138df601983613698565b91506138ea826138a9565b602082019050919050565b6000602082019050818103600083015261390e816138d2565b9050919050565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000613971602183613698565b915061397c82613915565b604082019050919050565b600060208201905081810360008301526139a081613964565b9050919050565b7f43616e6e6f74207769746864726177207468652072657761726420746f6b656e600082015250565b60006139dd602083613698565b91506139e8826139a7565b602082019050919050565b60006020820190508181036000830152613a0c816139d0565b9050919050565b613a1c81613336565b82525050565b6000602082019050613a376000830184613a13565b92915050565b600081519050613a4c81613230565b92915050565b600060208284031215613a6857613a6761313c565b5b6000613a7684828501613a3d565b91505092915050565b7f4e6f7420656e6f75676820746f6b656e7320746f207769746864726177000000600082015250565b6000613ab5601d83613698565b9150613ac082613a7f565b602082019050919050565b60006020820190508181036000830152613ae481613aa8565b9050919050565b7f556e61626c6520746f2077697468647261772030206c6f73742072657761726460008201527f7320746f6b656e73000000000000000000000000000000000000000000000000602082015250565b6000613b47602883613698565b9150613b5282613aeb565b604082019050919050565b60006020820190508181036000830152613b7681613b3a565b9050919050565b6000613b88826131fc565b9150613b93836131fc565b9250828203905081811115613bab57613baa61373b565b5b92915050565b7f416d6f756e742069732067726561746572207468616e20617661696c61626c6560008201527f206c6f7374207265776172647300000000000000000000000000000000000000602082015250565b6000613c0d602d83613698565b9150613c1882613bb1565b604082019050919050565b60006020820190508181036000830152613c3c81613c00565b9050919050565b7f556e61626c6520746f20776974686472617720302070726f6772616d2074617860008201527f6573000000000000000000000000000000000000000000000000000000000000602082015250565b6000613c9f602283613698565b9150613caa82613c43565b604082019050919050565b60006020820190508181036000830152613cce81613c92565b9050919050565b7f416d6f756e742069732067726561746572207468616e20617661696c61626c6560008201527f2074617865730000000000000000000000000000000000000000000000000000602082015250565b6000613d31602683613698565b9150613d3c82613cd5565b604082019050919050565b60006020820190508181036000830152613d6081613d24565b9050919050565b7f556e61626c6520746f20776974686472617720302072657761726420746f6b6560008201527f6e73000000000000000000000000000000000000000000000000000000000000602082015250565b6000613dc3602283613698565b9150613dce82613d67565b604082019050919050565b60006020820190508181036000830152613df281613db6565b9050919050565b7f556e61626c6520746f207769746864726177206d6f7265207468616e2074686560008201527f2070726f6772616d207265776172642072656d61696e696e6700000000000000602082015250565b6000613e55603983613698565b9150613e6082613df9565b604082019050919050565b60006020820190508181036000830152613e8481613e48565b9050919050565b7f5374616b696e672070726f6772616d206e6f74206f70656e2079657400000000600082015250565b6000613ec1601c83613698565b9150613ecc82613e8b565b602082019050919050565b60006020820190508181036000830152613ef081613eb4565b9050919050565b6000613f028261346e565b9150613f0d8361346e565b9250828203905067ffffffffffffffff811115613f2d57613f2c61373b565b5b92915050565b7f4e65772070726f6772616d206465706c6574696f6e2064617465206d7573742060008201527f62652067726561746572207468616e2063757272656e742074696d6500000000602082015250565b6000613f8f603c83613698565b9150613f9a82613f33565b604082019050919050565b60006020820190508181036000830152613fbe81613f82565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000613ffb601f83613698565b915061400682613fc5565b602082019050919050565b6000602082019050818103600083015261402a81613fee565b9050919050565b60006060820190506140466000830186613a13565b6140536020830185613a13565b6140606040830184613206565b949350505050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061409e601083613698565b91506140a982614068565b602082019050919050565b600060208201905081810360008301526140cd81614091565b9050919050565b7f4e6f7420656e6f756768207265776172647320746f20636c61696d0000000000600082015250565b600061410a601b83613698565b9150614115826140d4565b602082019050919050565b60006020820190508181036000830152614139816140fd565b9050919050565b60006040820190506141556000830185613a13565b6141626020830184613206565b9392505050565b7f4e6f20616d6f756e7420746f2077697468647261770000000000000000000000600082015250565b600061419f601583613698565b91506141aa82614169565b602082019050919050565b600060208201905081810360008301526141ce81614192565b9050919050565b7f416d6f756e7420746f207769746864726177206973206772656174657220746860008201527f616e207374616b65640000000000000000000000000000000000000000000000602082015250565b6000614231602983613698565b915061423c826141d5565b604082019050919050565b6000602082019050818103600083015261426081614224565b9050919050565b7f556e61626c6520746f207769746864726177203020746f6b656e730000000000600082015250565b600061429d601b83613698565b91506142a882614267565b602082019050919050565b600060208201905081810360008301526142cc81614290565b9050919050565b7f5468652066696e616c207374616b656420616d6f756e7420776f756c6420626560008201527f206c657373207468616e2072657175697265642062792074686520737065636960208201527f666965642070726f6772616d0000000000000000000000000000000000000000604082015250565b6000614355604c83613698565b9150614360826142d3565b606082019050919050565b6000602082019050818103600083015261438481614348565b9050919050565b7f546865726520617265206e6f2072657761726473206465706f7369746564207960008201527f6574000000000000000000000000000000000000000000000000000000000000602082015250565b60006143e7602283613698565b91506143f28261438b565b604082019050919050565b60006020820190508181036000830152614416816143da565b9050919050565b7f5374616b696e672070726f6772616d2068617320636c6f736564000000000000600082015250565b6000614453601a83613698565b915061445e8261441d565b602082019050919050565b6000602082019050818103600083015261448281614446565b9050919050565b7f556e61626c6520746f207374616b65203020746f6b656e730000000000000000600082015250565b60006144bf601883613698565b91506144ca82614489565b602082019050919050565b600060208201905081810360008301526144ee816144b2565b9050919050565b7f5374616b696e67206c657373207468616e20726571756972656420627920746860008201527f65207370656369666965642070726f6772616d00000000000000000000000000602082015250565b6000614551603383613698565b915061455c826144f5565b604082019050919050565b6000602082019050818103600083015261458081614544565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006145f76017836145b6565b9150614602826145c1565b601782019050919050565b600081519050919050565b60005b8381101561463657808201518184015260208101905061461b565b60008484015250505050565b600061464d8261460d565b61465781856145b6565b9350614667818560208601614618565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b60006146a96011836145b6565b91506146b482614673565b601182019050919050565b60006146ca826145ea565b91506146d68285614642565b91506146e18261469c565b91506146ed8284614642565b91508190509392505050565b6000601f19601f8301169050919050565b60006147158261460d565b61471f8185613698565b935061472f818560208601614618565b614738816146f9565b840191505092915050565b6000602082019050818103600083015261475d818461470a565b905092915050565b6000815190506147748161352a565b92915050565b6000602082840312156147905761478f61313c565b5b600061479e84828501614765565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614803602a83613698565b915061480e826147a7565b604082019050919050565b60006020820190508181036000830152614832816147f6565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061486f601483613698565b915061487a82614839565b602082019050919050565b6000602082019050818103600083015261489e81614862565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061490e826131fc565b9150600082036149215761492061373b565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000614962602083613698565b915061496d8261492c565b602082019050919050565b6000602082019050818103600083015261499181614955565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006149f4602683613698565b91506149ff82614998565b604082019050919050565b60006020820190508181036000830152614a23816149e7565b9050919050565b600081519050919050565b600081905092915050565b6000614a4b82614a2a565b614a558185614a35565b9350614a65818560208601614618565b80840191505092915050565b6000614a7d8284614a40565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614abe601d83613698565b9150614ac982614a88565b602082019050919050565b60006020820190508181036000830152614aed81614ab1565b905091905056fea2646970667358221220bc9c2003d2e09db21d5df4bc722aa9ebcdd59632b8474e96b57bf93a82ad0f8a64736f6c634300081200330000000000000000000000006758647a4cd6b4225b922b456be5c0535901203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000006758647a4cd6b4225b922b456be5c053590120320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006480b7900000000000000000000000000000000000000000000000000000000064fa019000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005a1d6f6051dfb04962bdb78b3ac01f3a6d817af600000000000000000000000004891a6b907a53e01797404d9af0e605ad260efb0000000000000000000000006d64004a60eda219690014acf783f833f4f868f6
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102695760003560e01c806381014fe411610151578063abe50f19116100c3578063cdf24c2f11610087578063cdf24c2f146106a7578063d37e51da146106c5578063d547741f146106e3578063f7c618c1146106ff578063f854a27f1461071d578063fb9604ce1461074e57610269565b8063abe50f1914610629578063b12ed45e14610645578063bd5c566414610663578063c4b8d27d14610681578063c9e721aa1461069d57610269565b8063a217fddf11610115578063a217fddf14610568578063a728517614610586578063a7c8a9e6146105a2578063a87430ba146105be578063a9170d81146105ef578063aa8172301461060d57610269565b806381014fe4146104d85780638456cb59146104f65780638980f11f1461050057806391d148541461051c57806392930b451461054c57610269565b806336568abe116101ea5780635c975abb116101ae5780635c975abb14610424578063643059161461044257806372f702f3146104605780637718d1e21461047e5780637f91d2351461049c5780638021e4a2146104ba57610269565b806336568abe146103ba578063372500ab146103d65780633f4ba83a146103e057806348928d57146103ea5780635992c85c1461040857610269565b8063230f289711610231578063230f289714610314578063248a9ca31461033257806325c065b1146103625780632876d7e4146103805780632f2ff15d1461039e57610269565b806301ffc9a71461026e57806306e0cf651461029e5780630f8cc3fd146102bc57806312d3b8c9146102da57806316992873146102f8575b600080fd5b61028860048036038101906102839190613199565b61076a565b60405161029591906131e1565b60405180910390f35b6102a66107e4565b6040516102b39190613215565b60405180910390f35b6102c46107ea565b6040516102d19190613215565b60405180910390f35b6102e26107f0565b6040516102ef9190613215565b60405180910390f35b610312600480360381019061030d919061325c565b6107f6565b005b61031c61094d565b6040516103299190613215565b60405180910390f35b61034c600480360381019061034791906132bf565b610953565b60405161035991906132fb565b60405180910390f35b61036a610973565b6040516103779190613215565b60405180910390f35b610388610979565b6040516103959190613215565b60405180910390f35b6103b860048036038101906103b39190613374565b61097f565b005b6103d460048036038101906103cf9190613374565b6109a0565b005b6103de610a23565b005b6103e8610a4f565b005b6103f2610a84565b6040516103ff9190613215565b60405180910390f35b610422600480360381019061041d91906133b4565b610a8a565b005b61042c610b53565b60405161043991906131e1565b60405180910390f35b61044a610b6a565b60405161045791906132fb565b60405180910390f35b610468610b8e565b6040516104759190613453565b60405180910390f35b610486610bb2565b6040516104939190613215565b60405180910390f35b6104a4610bb8565b6040516104b19190613215565b60405180910390f35b6104c2610bbe565b6040516104cf9190613491565b60405180910390f35b6104e0610bd8565b6040516104ed9190613215565b60405180910390f35b6104fe610bde565b005b61051a600480360381019061051591906134ea565b610c13565b005b61053660048036038101906105319190613374565b610eb0565b60405161054391906131e1565b60405180910390f35b61056660048036038101906105619190613556565b610f1b565b005b610570610f43565b60405161057d91906132fb565b60405180910390f35b6105a0600480360381019061059b919061325c565b610f4a565b005b6105bc60048036038101906105b7919061325c565b61108e565b005b6105d860048036038101906105d391906135a9565b6111d2565b6040516105e69291906135d6565b60405180910390f35b6105f76111f6565b6040516106049190613215565b60405180910390f35b610627600480360381019061062291906133b4565b61120b565b005b610643600480360381019061063e91906135ff565b611285565b005b61064d6112ab565b60405161065a91906132fb565b60405180910390f35b61066b6112cf565b6040516106789190613491565b60405180910390f35b61069b6004803603810190610696919061325c565b6112f3565b005b6106a561148d565b005b6106af61152f565b6040516106bc9190613215565b60405180910390f35b6106cd611535565b6040516106da9190613491565b60405180910390f35b6106fd60048036038101906106f89190613374565b61154f565b005b610707611570565b6040516107149190613453565b60405180910390f35b610737600480360381019061073291906135a9565b611594565b6040516107459291906135d6565b60405180910390f35b6107686004803603810190610763919061366b565b61177a565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107dd57506107dc82611886565b5b9050919050565b60055481565b60085481565b60045481565b6107fe6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6108288161193f565b6000821161086b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108629061371b565b60405180910390fd5b6108bf610876611953565b30847f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff1661195b909392919063ffffffff16565b81600660008282546108d1919061376a565b925050819055507fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166040516109399392919061379e565b60405180910390a15061094a6119e4565b50565b60065481565b600060026000838152602001908152602001600020600101549050919050565b60035481565b60075481565b61098882610953565b6109918161193f565b61099b83836119ee565b505050565b6109a8611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0c90613847565b60405180910390fd5b610a1f8282611acf565b5050565b610a2b6118f0565b610a33611bb1565b610a3b611bfb565b610a456000611dae565b610a4d6119e4565b565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610a798161193f565b610a81612030565b50565b600d5481565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef476610ab48161193f565b81600a84610ac29190613867565b1115610b03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afa906138f5565b60405180910390fd5b82600b8190555081600c819055507f091392e521f32b928e7effd1b5ff766e8c6faf01f5aceb57f54dc32cd2f57583600b54600c54604051610b469291906135d6565b60405180910390a1505050565b6000600160009054906101000a900460ff16905090565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec81565b7f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203281565b600c5481565b600e5481565b600a60089054906101000a900467ffffffffffffffff1681565b600b5481565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610c088161193f565b610c10612093565b50565b610c1b6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610c458161193f565b7f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610cd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cca90613987565b60405180910390fd5b7f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610d61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d58906139f3565b60405180910390fd5b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d9c9190613a22565b602060405180830381865afa158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddd9190613a52565b905082811015610e22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1990613acb565b60405180910390fd5b610e54610e2d611953565b848673ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff167f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b184604051610e9a9190613215565b60405180910390a25050610eac6119e4565b5050565b60006002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b610f236118f0565b610f2b611bb1565b610f3683838361217b565b610f3e6119e4565b505050565b6000801b81565b610f526118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec610f7c8161193f565b60008211610fbf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb690613b5d565b60405180910390fd5b6000600954600854610fd19190613b7d565b905080831115611016576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100d90613c23565b60405180910390fd5b8260096000828254611028919061376a565b9250508190555061108161103a611953565b847f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b505061108b6119e4565b50565b6110966118f0565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef4766110c08161193f565b60008211611103576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110fa90613cb5565b60405180910390fd5b6000600e54600d546111159190613b7d565b90508083111561115a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115190613d47565b60405180910390fd5b82600e600082825461116c919061376a565b925050819055506111c561117e611953565b847f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b50506111cf6119e4565b50565b600f6020528060005260406000206000915090508060000154908060010154905082565b701d6329f1c35ca4bfabb9f561000000000081565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6112358161193f565b82600381905550816004819055507f14207e149af257f57a5573a804ff84d3f14a60673e606ec6c2acdd9f70c355226003546004546040516112789291906135d6565b60405180910390a1505050565b61128d6118f0565b611295611bb1565b61129f8282612560565b6112a76119e4565b5050565b7f969e743677c83a4458df4afcef9c1049579c1137c04e48694290c3e5fe6ef47681565b7f000000000000000000000000000000000000000000000000000000006480b79081565b6112fb6118f0565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6113258161193f565b60008211611368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f90613dd9565b60405180910390fd5b6006548211156113ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a490613e6b565b60405180910390fd5b81600660008282546113bf9190613b7d565b925050819055506114186113d1611953565b837f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b7fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166040516114799392919061379e565b60405180910390a15061148a6119e4565b50565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6114b78161193f565b7f000000000000000000000000000000000000000000000000000000006480b79067ffffffffffffffff16421015611524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151b90613ed7565b60405180910390fd5b61152c611bfb565b50565b60095481565b600a60009054906101000a900467ffffffffffffffff1681565b61155882610953565b6115618161193f565b61156b8383611acf565b505050565b7f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203281565b60008060006115c342600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff166128e5565b90506000600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff166115ff9190613ef7565b90506000600a60089054906101000a900467ffffffffffffffff16836116259190613ef7565b90506000808367ffffffffffffffff16111561165f5761165c6006548367ffffffffffffffff168567ffffffffffffffff166128fe565b90505b60006007549050600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff168567ffffffffffffffff16111580156116a257506000600554115b156116d3576116c582701d6329f1c35ca4bfabb9f56100000000006005546128fe565b816116d0919061376a565b90505b611768600f60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015483600b54600c546129d9565b80975081985050505050505050915091565b7fbde745d383bd90948c6bf528cf5a56a9fe775bfee56a5d53b36fd785802b88ec6117a48161193f565b428267ffffffffffffffff16116117f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e790613fa5565b60405180910390fd5b81600a60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fed3478da81eace932babc39c0291e9731a6cc6249b5199cc742ec19a720bcc57600654600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff1660405161187a9392919061379e565b60405180910390a15050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600260005403611935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192c90614011565b60405180910390fd5b6002600081905550565b6119508161194b611953565b612a33565b50565b600033905090565b6119de846323b872dd60e01b85858560405160240161197c93929190614031565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612ab8565b50505050565b6001600081905550565b6119f88282610eb0565b611acb5760016002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611a70611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b611ad98282610eb0565b15611bad5760006002600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b52611953565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611bb9610b53565b15611bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf0906140b4565b60405180910390fd5b565b6000611c2742600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff166128e5565b90506000600a60089054906101000a900467ffffffffffffffff16600a60009054906101000a900467ffffffffffffffff16611c639190613ef7565b905060008167ffffffffffffffff1603611c7e575050611dac565b6000600a60089054906101000a900467ffffffffffffffff1683611ca29190613ef7565b90506000611cc76006548367ffffffffffffffff168567ffffffffffffffff166128fe565b90506000806005541115611d1357611cf382701d6329f1c35ca4bfabb9f56100000000006005546128fe565b90508060076000828254611d07919061376a565b92505081905550611d64565b8160086000828254611d25919061376a565b925050819055507fa641ca195988b20fb3185bbfd64521b79089ad0913255a52c171bac83783bdda82604051611d5b9190613215565b60405180910390a15b8160066000828254611d769190613b7d565b9250508190555084600a60086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050505b565b600080611e56600f6000611dc0611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f6000611e0a611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154600754600b54600c546129d9565b9150915060045482101580611e685750825b611ea7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9e90614120565b60405180910390fd5b600754600f6000611eb6611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055508215611f68578082611f09919061376a565b60086000828254611f1a919061376a565b925050819055507fa641ca195988b20fb3185bbfd64521b79089ad0913255a52c171bac83783bdda8183611f4e919061376a565b604051611f5b9190613215565b60405180910390a161202b565b80600d6000828254611f7a919061376a565b92505081905550611fd3611f8c611953565b837f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b611fdb611953565b73ffffffffffffffffffffffffffffffffffffffff167fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e32583836040516120229291906135d6565b60405180910390a25b505050565b612038612b7f565b6000600160006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61207c611953565b6040516120899190613a22565b60405180910390a1565b61209b611bb1565b60018060006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120de611953565b6040516120eb9190613a22565b60405180910390a1565b6121768363a9059cbb60e01b8484604051602401612114929190614140565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612ab8565b505050565b6000600f6000612189611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403612207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fe906141b5565b60405180910390fd5b82600f6000612214611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541015612293576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228a90614247565b60405180910390fd5b600083116122d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122cd906142b3565b60405180910390fd5b82600f60006122e3611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541480612383575060035483600f6000612338611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546123809190613b7d565b10155b6123c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b99061436b565b60405180910390fd5b6123ca611bfb565b600083600f60006123d9611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546124219190613b7d565b9050828061242f5750600081145b156124425761243d82611dae565b61244c565b61244b81612bc8565b5b80600f6000612459611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555083600560008282546124ac9190613b7d565b925050819055506125056124be611953565b857f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff166120f59092919063ffffffff16565b61250d611953565b73ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5856040516125529190613215565b60405180910390a250505050565b7f000000000000000000000000000000000000000000000000000000006480b79067ffffffffffffffff164210156125cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125c490613ed7565b60405180910390fd5b600060065411612612576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612609906143fd565b60405180910390fd5b600a60009054906101000a900467ffffffffffffffff1667ffffffffffffffff164210612674576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266b90614469565b60405180910390fd5b600082116126b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126ae906144d5565b60405180910390fd5b600354600f60006126c6611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001548361270f919061376a565b1015612750576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161274790614567565b60405180910390fd5b6127a461275b611953565b30847f0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203273ffffffffffffffffffffffffffffffffffffffff1661195b909392919063ffffffff16565b6127ac611bfb565b600082600f60006127bb611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154612803919061376a565b9050811561281a576128156000611dae565b612824565b61282381612bc8565b5b80600f6000612831611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055508260056000828254612884919061376a565b92505081905550612893611953565b73ffffffffffffffffffffffffffffffffffffffff167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d846040516128d89190613215565b60405180910390a2505050565b60008183106128f457816128f6565b825b905092915050565b60008060008019858709858702925082811083820303915050600081036129395783828161292f5761292e614587565b5b04925050506129d2565b80841161294557600080fd5b60008486880990508281118203915080830392506000600186190186169050808604955080840493506001818260000304019050808302841793506000600287600302189050808702600203810290508087026002038102905080870260020381029050808702600203810290508087026002038102905080870260020381029050808502955050505050505b9392505050565b600080600087866129ea9190613b7d565b90506000612a0a8289701d6329f1c35ca4bfabb9f56100000000006128fe565b9050612a178187876128fe565b92508281612a259190613b7d565b935050509550959350505050565b612a3d8282610eb0565b612ab457612a4a81612d06565b612a588360001c6020612d33565b604051602001612a699291906146bf565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aab9190614743565b60405180910390fd5b5050565b6000612b1a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612f6f9092919063ffffffff16565b9050600081511115612b7a5780806020019051810190612b3a919061477a565b612b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b7090614819565b60405180910390fd5b5b505050565b612b87610b53565b612bc6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bbd90614885565b60405180910390fd5b565b600080612c70600f6000612bda611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154600f6000612c24611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154600754600b54600c546129d9565b9150915060008183612c82919061376a565b90506000612ca282701d6329f1c35ca4bfabb9f5610000000000876128fe565b905080600754612cb29190613b7d565b600f6000612cbe611953565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055505050505050565b6060612d2c8273ffffffffffffffffffffffffffffffffffffffff16601460ff16612d33565b9050919050565b606060006002836002612d469190613867565b612d50919061376a565b67ffffffffffffffff811115612d6957612d686148a5565b5b6040519080825280601f01601f191660200182016040528015612d9b5781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612dd357612dd26148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612e3757612e366148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002612e779190613867565b612e81919061376a565b90505b6001811115612f21577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612ec357612ec26148d4565b5b1a60f81b828281518110612eda57612ed96148d4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612f1a90614903565b9050612e84565b5060008414612f65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5c90614978565b60405180910390fd5b8091505092915050565b6060612f7e8484600085612f87565b90509392505050565b606082471015612fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fc390614a0a565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612ff59190614a71565b60006040518083038185875af1925050503d8060008114613032576040519150601f19603f3d011682016040523d82523d6000602084013e613037565b606091505b509150915061304887838387613054565b92505050949350505050565b606083156130b65760008351036130ae5761306e856130c9565b6130ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a490614ad4565b60405180910390fd5b5b8290506130c1565b6130c083836130ec565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000825111156130ff5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131339190614743565b60405180910390fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61317681613141565b811461318157600080fd5b50565b6000813590506131938161316d565b92915050565b6000602082840312156131af576131ae61313c565b5b60006131bd84828501613184565b91505092915050565b60008115159050919050565b6131db816131c6565b82525050565b60006020820190506131f660008301846131d2565b92915050565b6000819050919050565b61320f816131fc565b82525050565b600060208201905061322a6000830184613206565b92915050565b613239816131fc565b811461324457600080fd5b50565b60008135905061325681613230565b92915050565b6000602082840312156132725761327161313c565b5b600061328084828501613247565b91505092915050565b6000819050919050565b61329c81613289565b81146132a757600080fd5b50565b6000813590506132b981613293565b92915050565b6000602082840312156132d5576132d461313c565b5b60006132e3848285016132aa565b91505092915050565b6132f581613289565b82525050565b600060208201905061331060008301846132ec565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061334182613316565b9050919050565b61335181613336565b811461335c57600080fd5b50565b60008135905061336e81613348565b92915050565b6000806040838503121561338b5761338a61313c565b5b6000613399858286016132aa565b92505060206133aa8582860161335f565b9150509250929050565b600080604083850312156133cb576133ca61313c565b5b60006133d985828601613247565b92505060206133ea85828601613247565b9150509250929050565b6000819050919050565b600061341961341461340f84613316565b6133f4565b613316565b9050919050565b600061342b826133fe565b9050919050565b600061343d82613420565b9050919050565b61344d81613432565b82525050565b60006020820190506134686000830184613444565b92915050565b600067ffffffffffffffff82169050919050565b61348b8161346e565b82525050565b60006020820190506134a66000830184613482565b92915050565b60006134b782613336565b9050919050565b6134c7816134ac565b81146134d257600080fd5b50565b6000813590506134e4816134be565b92915050565b600080604083850312156135015761350061313c565b5b600061350f858286016134d5565b925050602061352085828601613247565b9150509250929050565b613533816131c6565b811461353e57600080fd5b50565b6000813590506135508161352a565b92915050565b60008060006060848603121561356f5761356e61313c565b5b600061357d86828701613247565b935050602061358e86828701613541565b925050604061359f86828701613541565b9150509250925092565b6000602082840312156135bf576135be61313c565b5b60006135cd8482850161335f565b91505092915050565b60006040820190506135eb6000830185613206565b6135f86020830184613206565b9392505050565b600080604083850312156136165761361561313c565b5b600061362485828601613247565b925050602061363585828601613541565b9150509250929050565b6136488161346e565b811461365357600080fd5b50565b6000813590506136658161363f565b92915050565b6000602082840312156136815761368061313c565b5b600061368f84828501613656565b91505092915050565b600082825260208201905092915050565b7f556e61626c6520746f206465706f73697420302072657761726420746f6b656e60008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000613705602183613698565b9150613710826136a9565b604082019050919050565b60006020820190508181036000830152613734816136f8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613775826131fc565b9150613780836131fc565b92508282019050808211156137985761379761373b565b5b92915050565b60006060820190506137b36000830186613206565b6137c06020830185613482565b6137cd6040830184613482565b949350505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000613831602f83613698565b915061383c826137d5565b604082019050919050565b6000602082019050818103600083015261386081613824565b9050919050565b6000613872826131fc565b915061387d836131fc565b925082820261388b816131fc565b915082820484148315176138a2576138a161373b565b5b5092915050565b7f54617820726174696f2065786365656473203130252063617000000000000000600082015250565b60006138df601983613698565b91506138ea826138a9565b602082019050919050565b6000602082019050818103600083015261390e816138d2565b9050919050565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000613971602183613698565b915061397c82613915565b604082019050919050565b600060208201905081810360008301526139a081613964565b9050919050565b7f43616e6e6f74207769746864726177207468652072657761726420746f6b656e600082015250565b60006139dd602083613698565b91506139e8826139a7565b602082019050919050565b60006020820190508181036000830152613a0c816139d0565b9050919050565b613a1c81613336565b82525050565b6000602082019050613a376000830184613a13565b92915050565b600081519050613a4c81613230565b92915050565b600060208284031215613a6857613a6761313c565b5b6000613a7684828501613a3d565b91505092915050565b7f4e6f7420656e6f75676820746f6b656e7320746f207769746864726177000000600082015250565b6000613ab5601d83613698565b9150613ac082613a7f565b602082019050919050565b60006020820190508181036000830152613ae481613aa8565b9050919050565b7f556e61626c6520746f2077697468647261772030206c6f73742072657761726460008201527f7320746f6b656e73000000000000000000000000000000000000000000000000602082015250565b6000613b47602883613698565b9150613b5282613aeb565b604082019050919050565b60006020820190508181036000830152613b7681613b3a565b9050919050565b6000613b88826131fc565b9150613b93836131fc565b9250828203905081811115613bab57613baa61373b565b5b92915050565b7f416d6f756e742069732067726561746572207468616e20617661696c61626c6560008201527f206c6f7374207265776172647300000000000000000000000000000000000000602082015250565b6000613c0d602d83613698565b9150613c1882613bb1565b604082019050919050565b60006020820190508181036000830152613c3c81613c00565b9050919050565b7f556e61626c6520746f20776974686472617720302070726f6772616d2074617860008201527f6573000000000000000000000000000000000000000000000000000000000000602082015250565b6000613c9f602283613698565b9150613caa82613c43565b604082019050919050565b60006020820190508181036000830152613cce81613c92565b9050919050565b7f416d6f756e742069732067726561746572207468616e20617661696c61626c6560008201527f2074617865730000000000000000000000000000000000000000000000000000602082015250565b6000613d31602683613698565b9150613d3c82613cd5565b604082019050919050565b60006020820190508181036000830152613d6081613d24565b9050919050565b7f556e61626c6520746f20776974686472617720302072657761726420746f6b6560008201527f6e73000000000000000000000000000000000000000000000000000000000000602082015250565b6000613dc3602283613698565b9150613dce82613d67565b604082019050919050565b60006020820190508181036000830152613df281613db6565b9050919050565b7f556e61626c6520746f207769746864726177206d6f7265207468616e2074686560008201527f2070726f6772616d207265776172642072656d61696e696e6700000000000000602082015250565b6000613e55603983613698565b9150613e6082613df9565b604082019050919050565b60006020820190508181036000830152613e8481613e48565b9050919050565b7f5374616b696e672070726f6772616d206e6f74206f70656e2079657400000000600082015250565b6000613ec1601c83613698565b9150613ecc82613e8b565b602082019050919050565b60006020820190508181036000830152613ef081613eb4565b9050919050565b6000613f028261346e565b9150613f0d8361346e565b9250828203905067ffffffffffffffff811115613f2d57613f2c61373b565b5b92915050565b7f4e65772070726f6772616d206465706c6574696f6e2064617465206d7573742060008201527f62652067726561746572207468616e2063757272656e742074696d6500000000602082015250565b6000613f8f603c83613698565b9150613f9a82613f33565b604082019050919050565b60006020820190508181036000830152613fbe81613f82565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000613ffb601f83613698565b915061400682613fc5565b602082019050919050565b6000602082019050818103600083015261402a81613fee565b9050919050565b60006060820190506140466000830186613a13565b6140536020830185613a13565b6140606040830184613206565b949350505050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061409e601083613698565b91506140a982614068565b602082019050919050565b600060208201905081810360008301526140cd81614091565b9050919050565b7f4e6f7420656e6f756768207265776172647320746f20636c61696d0000000000600082015250565b600061410a601b83613698565b9150614115826140d4565b602082019050919050565b60006020820190508181036000830152614139816140fd565b9050919050565b60006040820190506141556000830185613a13565b6141626020830184613206565b9392505050565b7f4e6f20616d6f756e7420746f2077697468647261770000000000000000000000600082015250565b600061419f601583613698565b91506141aa82614169565b602082019050919050565b600060208201905081810360008301526141ce81614192565b9050919050565b7f416d6f756e7420746f207769746864726177206973206772656174657220746860008201527f616e207374616b65640000000000000000000000000000000000000000000000602082015250565b6000614231602983613698565b915061423c826141d5565b604082019050919050565b6000602082019050818103600083015261426081614224565b9050919050565b7f556e61626c6520746f207769746864726177203020746f6b656e730000000000600082015250565b600061429d601b83613698565b91506142a882614267565b602082019050919050565b600060208201905081810360008301526142cc81614290565b9050919050565b7f5468652066696e616c207374616b656420616d6f756e7420776f756c6420626560008201527f206c657373207468616e2072657175697265642062792074686520737065636960208201527f666965642070726f6772616d0000000000000000000000000000000000000000604082015250565b6000614355604c83613698565b9150614360826142d3565b606082019050919050565b6000602082019050818103600083015261438481614348565b9050919050565b7f546865726520617265206e6f2072657761726473206465706f7369746564207960008201527f6574000000000000000000000000000000000000000000000000000000000000602082015250565b60006143e7602283613698565b91506143f28261438b565b604082019050919050565b60006020820190508181036000830152614416816143da565b9050919050565b7f5374616b696e672070726f6772616d2068617320636c6f736564000000000000600082015250565b6000614453601a83613698565b915061445e8261441d565b602082019050919050565b6000602082019050818103600083015261448281614446565b9050919050565b7f556e61626c6520746f207374616b65203020746f6b656e730000000000000000600082015250565b60006144bf601883613698565b91506144ca82614489565b602082019050919050565b600060208201905081810360008301526144ee816144b2565b9050919050565b7f5374616b696e67206c657373207468616e20726571756972656420627920746860008201527f65207370656369666965642070726f6772616d00000000000000000000000000602082015250565b6000614551603383613698565b915061455c826144f5565b604082019050919050565b6000602082019050818103600083015261458081614544565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006145f76017836145b6565b9150614602826145c1565b601782019050919050565b600081519050919050565b60005b8381101561463657808201518184015260208101905061461b565b60008484015250505050565b600061464d8261460d565b61465781856145b6565b9350614667818560208601614618565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b60006146a96011836145b6565b91506146b482614673565b601182019050919050565b60006146ca826145ea565b91506146d68285614642565b91506146e18261469c565b91506146ed8284614642565b91508190509392505050565b6000601f19601f8301169050919050565b60006147158261460d565b61471f8185613698565b935061472f818560208601614618565b614738816146f9565b840191505092915050565b6000602082019050818103600083015261475d818461470a565b905092915050565b6000815190506147748161352a565b92915050565b6000602082840312156147905761478f61313c565b5b600061479e84828501614765565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614803602a83613698565b915061480e826147a7565b604082019050919050565b60006020820190508181036000830152614832816147f6565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061486f601483613698565b915061487a82614839565b602082019050919050565b6000602082019050818103600083015261489e81614862565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061490e826131fc565b9150600082036149215761492061373b565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000614962602083613698565b915061496d8261492c565b602082019050919050565b6000602082019050818103600083015261499181614955565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006149f4602683613698565b91506149ff82614998565b604082019050919050565b60006020820190508181036000830152614a23816149e7565b9050919050565b600081519050919050565b600081905092915050565b6000614a4b82614a2a565b614a558185614a35565b9350614a65818560208601614618565b80840191505092915050565b6000614a7d8284614a40565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614abe601d83613698565b9150614ac982614a88565b602082019050919050565b60006020820190508181036000830152614aed81614ab1565b905091905056fea2646970667358221220bc9c2003d2e09db21d5df4bc722aa9ebcdd59632b8474e96b57bf93a82ad0f8a64736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006758647a4cd6b4225b922b456be5c0535901203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000006758647a4cd6b4225b922b456be5c053590120320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006480b7900000000000000000000000000000000000000000000000000000000064fa019000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005a1d6f6051dfb04962bdb78b3ac01f3a6d817af600000000000000000000000004891a6b907a53e01797404d9af0e605ad260efb0000000000000000000000006d64004a60eda219690014acf783f833f4f868f6
-----Decoded View---------------
Arg [0] : _stakingToken (address): 0x6758647a4Cd6b4225b922b456Be5C05359012032
Arg [1] : _minStakingAmount (uint256): 0
Arg [2] : _rewardToken (address): 0x6758647a4Cd6b4225b922b456Be5C05359012032
Arg [3] : _minRewardAmount (uint256): 0
Arg [4] : _programStartsAt (uint64): 1686157200
Arg [5] : _programRewardsDepletionAt (uint64): 1694106000
Arg [6] : _taxRatioNumerator (uint256): 5
Arg [7] : _taxRatioDenominator (uint256): 100
Arg [8] : managers (address[]): 0x5A1d6F6051DFB04962bDB78B3AC01F3a6D817aF6,0x04891a6b907a53e01797404D9af0e605AD260efb,0x6d64004A60edA219690014Acf783F833f4F868f6
-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 0000000000000000000000006758647a4cd6b4225b922b456be5c05359012032
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000006758647a4cd6b4225b922b456be5c05359012032
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 000000000000000000000000000000000000000000000000000000006480b790
Arg [5] : 0000000000000000000000000000000000000000000000000000000064fa0190
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [10] : 0000000000000000000000005a1d6f6051dfb04962bdb78b3ac01f3a6d817af6
Arg [11] : 00000000000000000000000004891a6b907a53e01797404d9af0e605ad260efb
Arg [12] : 0000000000000000000000006d64004a60eda219690014acf783f833f4f868f6
Deployed Bytecode Sourcemap
720:17515:13:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2606:202:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1258:37:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1390:32;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1176:30;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14048:464;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1301:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4378:129:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1097:31:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1344:40;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4803:145:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5912:214;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4676:226:13;;;:::i;:::-;;18155:78;;;:::i;:::-;;1646:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16984:454;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1615:84:2;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;928:64:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1055:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1606:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1681:38;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1520:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1568:32;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18075:74;;;:::i;:::-;;17444:625;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2895:145:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4432:238:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2027:49:0;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15118:531:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;15655:485;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1835:44;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;999:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16665:313;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4253:173;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;838:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1213:39;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14518:594;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13821:221;;;:::i;:::-;;1428:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1475:39;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5228:147:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1135:35:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5061:1541;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;16146:513;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2606:202:0;2691:4;2729:32;2714:47;;;:11;:47;;;;:87;;;;2765:36;2789:11;2765:23;:36::i;:::-;2714:87;2707:94;;2606:202;;;:::o;1258:37:13:-;;;;:::o;1390:32::-;;;;:::o;1176:30::-;;;;:::o;14048:464::-;2261:21:3;:19;:21::i;:::-;967:25:13::1;2505:16:0;2516:4;2505:10;:16::i;:::-;14183:1:13::2;14173:7;:11;14165:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;14232:66;14261:12;:10;:12::i;:::-;14283:4;14290:7;14232:11;:28;;;;:66;;;;;;:::i;:::-;14334:7;14308:22;;:33;;;;;;;:::i;:::-;;;;;;;;14356:149;14393:22;;14429:27;;;;;;;;;;;14470:25;;;;;;;;;;;14356:149;;;;;;;;:::i;:::-;;;;;;;;2292:1:3::1;2303:20:::0;:18;:20::i;:::-;14048:464:13;:::o;1301:37::-;;;;:::o;4378:129:0:-;4452:7;4478:6;:12;4485:4;4478:12;;;;;;;;;;;:22;;;4471:29;;4378:129;;;:::o;1097:31:13:-;;;;:::o;1344:40::-;;;;:::o;4803:145:0:-;4886:18;4899:4;4886:12;:18::i;:::-;2505:16;2516:4;2505:10;:16::i;:::-;4916:25:::1;4927:4;4933:7;4916:10;:25::i;:::-;4803:145:::0;;;:::o;5912:214::-;6018:12;:10;:12::i;:::-;6007:23;;:7;:23;;;5999:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;6093:26;6105:4;6111:7;6093:11;:26::i;:::-;5912:214;;:::o;4676:226:13:-;2261:21:3;:19;:21::i;:::-;1239:19:2::1;:17;:19::i;:::-;4843:22:13::2;:20;:22::i;:::-;4875:20;4889:5;4875:13;:20::i;:::-;2303::3::0;:18;:20::i;:::-;4676:226:13:o;18155:78::-;967:25;2505:16:0;2516:4;2505:10;:16::i;:::-;18216:10:13::1;:8;:10::i;:::-;18155:78:::0;:::o;1646:29::-;;;;:::o;16984:454::-;891:31;2505:16:0;2516:4;2505:10;:16::i;:::-;17186:20:13::1;17180:2;17159:18;:23;;;;:::i;:::-;:47;;17138:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;17287:18;17267:17;:38;;;;17337:20;17315:19;:42;;;;17372:59;17392:17;;17411:19;;17372:59;;;;;;;:::i;:::-;;;;;;;;16984:454:::0;;;:::o;1615:84:2:-;1662:4;1685:7;;;;;;;;;;;1678:14;;1615:84;:::o;928:64:13:-;967:25;928:64;:::o;1055:36::-;;;:::o;1606:34::-;;;;:::o;1681:38::-;;;;:::o;1520:41::-;;;;;;;;;;;;;:::o;1568:32::-;;;;:::o;18075:74::-;967:25;2505:16:0;2516:4;2505:10;:16::i;:::-;18134:8:13::1;:6;:8::i;:::-;18075:74:::0;:::o;17444:625::-;2261:21:3;:19;:21::i;:::-;967:25:13::1;2505:16:0;2516:4;2505:10;:16::i;:::-;17620:12:13::2;17594:39;;17602:5;17594:39;;::::0;17573:119:::2;;;;;;;;;;;;:::i;:::-;;;;;;;;;17749:11;17723:38;;17731:5;17723:38;;::::0;17702:117:::2;;;;;;;;;;;;:::i;:::-;;;;;;;;;17830:20;17853:5;:15;;;17877:4;17853:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17830:53;;17917:6;17901:12;:22;;17893:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;17968:40;17987:12;:10;:12::i;:::-;18001:6;17968:5;:18;;;;:40;;;;;:::i;:::-;18047:5;18024:38;;;18055:6;18024:38;;;;;;:::i;:::-;;;;;;;;17563:506;2292:1:3::1;2303:20:::0;:18;:20::i;:::-;17444:625:13;;:::o;2895:145:0:-;2981:4;3004:6;:12;3011:4;3004:12;;;;;;;;;;;:20;;:29;3025:7;3004:29;;;;;;;;;;;;;;;;;;;;;;;;;2997:36;;2895:145;;;;:::o;4432:238:13:-;2261:21:3;:19;:21::i;:::-;1239:19:2::1;:17;:19::i;:::-;4599:64:13::2;4609:7;4618:21;4641;4599:9;:64::i;:::-;2303:20:3::0;:18;:20::i;:::-;4432:238:13;;;:::o;2027:49:0:-;2072:4;2027:49;;;:::o;15118:531:13:-;2261:21:3;:19;:21::i;:::-;967:25:13::1;2505:16:0;2516:4;2505:10;:16::i;:::-;15258:1:13::2;15248:7;:11;15240:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;15314:29;15378:26;;15346:17;;:58;;;;:::i;:::-;15314:90;;15446:21;15435:7;:32;;15414:124;;;;;;;;;;;;:::i;:::-;;;;;;;;;15578:7;15548:26;;:37;;;;;;;:::i;:::-;;;;;;;;15595:47;15620:12;:10;:12::i;:::-;15634:7;15595:11;:24;;;;:47;;;;;:::i;:::-;15230:419;2292:1:3::1;2303:20:::0;:18;:20::i;:::-;15118:531:13;:::o;15655:485::-;2261:21:3;:19;:21::i;:::-;891:31:13::1;2505:16:0;2516:4;2505:10;:16::i;:::-;15795:1:13::2;15785:7;:11;15777:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;15845:23;15888;;15871:14;;:40;;;;:::i;:::-;15845:66;;15953:15;15942:7;:26;;15921:111;;;;;;;;;;;;:::i;:::-;;;;;;;;;16069:7;16042:23;;:34;;;;;;;:::i;:::-;;;;;;;;16086:47;16111:12;:10;:12::i;:::-;16125:7;16086:11;:24;;;;:47;;;;;:::i;:::-;15767:373;2292:1:3::1;2303:20:::0;:18;:20::i;:::-;15655:485:13;:::o;1835:44::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;999:49::-;1044:4;999:49;:::o;16665:313::-;967:25;2505:16:0;2516:4;2505:10;:16::i;:::-;16835:17:13::1;16816:16;:36;;;;16880:16;16862:15;:34;;;;16911:60;16937:16;;16955:15;;16911:60;;;;;;;:::i;:::-;;;;;;;;16665:313:::0;;;:::o;4253:173::-;2261:21:3;:19;:21::i;:::-;1239:19:2::1;:17;:19::i;:::-;4381:38:13::2;4388:7;4397:21;4381:6;:38::i;:::-;2303:20:3::0;:18;:20::i;:::-;4253:173:13;;:::o;838:84::-;891:31;838:84;:::o;1213:39::-;;;:::o;14518:594::-;2261:21:3;:19;:21::i;:::-;967:25:13::1;2505:16:0;2516:4;2505:10;:16::i;:::-;14654:1:13::2;14644:7;:11;14636:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;14736:22;;14725:7;:33;;14704:137;;;;;;;;;;;;:::i;:::-;;;;;;;;;14877:7;14851:22;;:33;;;;;;;:::i;:::-;;;;;;;;14894:47;14919:12;:10;:12::i;:::-;14933:7;14894:11;:24;;;;:47;;;;;:::i;:::-;14956:149;14993:22;;15029:27;;;;;;;;;;;15070:25;;;;;;;;;;;14956:149;;;;;;;;:::i;:::-;;;;;;;;2292:1:3::1;2303:20:::0;:18;:20::i;:::-;14518:594:13;:::o;13821:221::-;967:25;2505:16:0;2516:4;2505:10;:16::i;:::-;13934:15:13::1;13915:34;;:15;:34;;13894:109;;;;;;;;;;;;:::i;:::-;;;;;;;;;14013:22;:20;:22::i;:::-;13821:221:::0;:::o;1428:41::-;;;;:::o;1475:39::-;;;;;;;;;;;;;:::o;5228:147:0:-;5312:18;5325:4;5312:12;:18::i;:::-;2505:16;2516:4;2505:10;:16::i;:::-;5342:26:::1;5354:4;5360:7;5342:11;:26::i;:::-;5228:147:::0;;;:::o;1135:35:13:-;;;:::o;5061:1541::-;5138:25;5165:18;5195:35;5253:52;5262:15;5279:25;;;;;;;;;;;5253:52;;:8;:52::i;:::-;5195:120;;5326:31;5400:27;;;;;;;;;;;5360:25;;;;;;;;;;;:67;;;;:::i;:::-;5326:101;;5438:28;5512:27;;;;;;;;;;;5469:28;:70;;;;:::i;:::-;5438:101;;5550:30;5626:1;5599:24;:28;;;5595:230;;;5668:146;5697:22;;5737:21;5668:146;;5776:24;5668:146;;:11;:146::i;:::-;5643:171;;5595:230;5835:38;5876:25;;5835:66;;6037:25;;;;;;;;;;;6005:57;;:28;:57;;;;:99;;;;;6103:1;6078:22;;:26;6005:99;5988:327;;;6163:141;6192:22;1044:4;6268:22;;6163:11;:141::i;:::-;6129:175;;;;;:::i;:::-;;;5988:327;6359:236;6398:5;:11;6404:4;6398:11;;;;;;;;;;;;;;;:41;;;6453:5;:11;6459:4;6453:11;;;;;;;;;;;;;;;:24;;;6491:30;6535:17;;6566:19;;6359:25;:236::i;:::-;6325:270;;;;;;;;5185:1417;;;;;5061:1541;;;:::o;16146:513::-;967:25;2505:16:0;2516:4;2505:10;:16::i;:::-;16323:15:13::1;16294:26;:44;;;16273:151;;;;;;;;;;;;:::i;:::-;;;;;;;;;16462:26;16434:25;;:54;;;;;;;;;;;;;;;;;;16503:149;16540:22;;16576:27;;;;;;;;;;;16617:25;;;;;;;;;;;16503:149;;;;;;;;:::i;:::-;;;;;;;;16146:513:::0;;:::o;829:155:10:-;914:4;952:25;937:40;;;:11;:40;;;;930:47;;829:155;;;:::o;2336:287:3:-;1759:1;2468:7;;:19;2460:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;1759:1;2598:7;:18;;;;2336:287::o;3334:103:0:-;3400:30;3411:4;3417:12;:10;:12::i;:::-;3400:10;:30::i;:::-;3334:103;:::o;640:96:8:-;693:7;719:10;712:17;;640:96;:::o;974:241:6:-;1112:96;1132:5;1162:27;;;1191:4;1197:2;1201:5;1139:68;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1112:19;:96::i;:::-;974:241;;;;:::o;2629:209:3:-;1716:1;2809:7;:22;;;;2629:209::o;7461:233:0:-;7544:22;7552:4;7558:7;7544;:22::i;:::-;7539:149;;7614:4;7582:6;:12;7589:4;7582:12;;;;;;;;;;;:20;;:29;7603:7;7582:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;7664:12;:10;:12::i;:::-;7637:40;;7655:7;7637:40;;7649:4;7637:40;;;;;;;;;;7539:149;7461:233;;:::o;7865:234::-;7948:22;7956:4;7962:7;7948;:22::i;:::-;7944:149;;;8018:5;7986:6;:12;7993:4;7986:12;;;;;;;;;;;:20;;:29;8007:7;7986:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;8069:12;:10;:12::i;:::-;8042:40;;8060:7;8042:40;;8054:4;8042:40;;;;;;;;;;7944:149;7865:234;;:::o;1767:106:2:-;1837:8;:6;:8::i;:::-;1836:9;1828:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;1767:106::o;11595:1356:13:-;11646:35;11704:52;11713:15;11730:25;;;;;;;;;;;11704:52;;:8;:52::i;:::-;11646:120;;11777:31;11851:27;;;;;;;;;;;11811:25;;;;;;;;;;;:67;;;;:::i;:::-;11777:101;;11996:1;11968:24;:29;;;11964:66;;12013:7;;;;11964:66;12040:28;12114:27;;;;;;;;;;;12071:28;:70;;;;:::i;:::-;12040:101;;12152:30;12185:130;12210:22;;12246:21;12185:130;;12281:24;12185:130;;:11;:130::i;:::-;12152:163;;12326:40;12410:1;12385:22;;:26;12381:436;;;12462:141;12491:22;1044:4;12567:22;;12462:11;:141::i;:::-;12427:176;;12646:32;12617:25;;:61;;;;;;;:::i;:::-;;;;;;;;12381:436;;;12730:22;12709:17;;:43;;;;;;;:::i;:::-;;;;;;;;12771:35;12783:22;12771:35;;;;;;:::i;:::-;;;;;;;;12381:436;12853:22;12827;;:48;;;;;;;:::i;:::-;;;;;;;;12916:28;12886:27;;:58;;;;;;;;;;;;;;;;;;11636:1315;;;;;11595:1356;:::o;9223:1062::-;9307:25;9346:18;9377:271;9420:5;:19;9426:12;:10;:12::i;:::-;9420:19;;;;;;;;;;;;;;;:49;;;9487:5;:19;9493:12;:10;:12::i;:::-;9487:19;;;;;;;;;;;;;;;:32;;;9537:25;;9580:17;;9615:19;;9377:25;:271::i;:::-;9293:355;;;;9701:15;;9680:17;:36;;:61;;;;9720:21;9680:61;9659:135;;;;;;;;;;;;:::i;:::-;;;;;;;;;9870:25;;9805:5;:19;9811:12;:10;:12::i;:::-;9805:19;;;;;;;;;;;;;;;:62;;:90;;;;9910:21;9906:373;;;9988:10;9968:17;:30;;;;:::i;:::-;9947:17;;:51;;;;;;;:::i;:::-;;;;;;;;10017:43;10049:10;10029:17;:30;;;;:::i;:::-;10017:43;;;;;;:::i;:::-;;;;;;;;9906:373;;;10109:10;10091:14;;:28;;;;;;;:::i;:::-;;;;;;;;10133:57;10158:12;:10;:12::i;:::-;10172:17;10133:11;:24;;;;:57;;;;;:::i;:::-;10224:12;:10;:12::i;:::-;10209:59;;;10238:17;10257:10;10209:59;;;;;;;:::i;:::-;;;;;;;;9906:373;9283:1002;;9223:1062;:::o;2433:117:2:-;1486:16;:14;:16::i;:::-;2501:5:::1;2491:7;;:15;;;;;;;;;;;;;;;;;;2521:22;2530:12;:10;:12::i;:::-;2521:22;;;;;;:::i;:::-;;;;;;;;2433:117::o:0;2186:115::-;1239:19;:17;:19::i;:::-;2255:4:::1;2245:7:::0;::::1;:14;;;;;;;;;;;;;;;;;;2274:20;2281:12;:10;:12::i;:::-;2274:20;;;;;;:::i;:::-;;;;;;;;2186:115::o:0;763:205:6:-;875:86;895:5;925:23;;;950:2;954:5;902:58;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;875:19;:86::i;:::-;763:205;;;:::o;7920:1297:13:-;8105:1;8069:5;:19;8075:12;:10;:12::i;:::-;8069:19;;;;;;;;;;;;;;;:32;;;:37;8061:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;8199:7;8163:5;:19;8169:12;:10;:12::i;:::-;8163:19;;;;;;;;;;;;;;;:32;;;:43;;8142:131;;;;;;;;;;;;:::i;:::-;;;;;;;;;8301:1;8291:7;:11;8283:51;;;;;;;;;;;;:::i;:::-;;;;;;;;;8401:7;8365:5;:19;8371:12;:10;:12::i;:::-;8365:19;;;;;;;;;;;;;;;:32;;;:43;:125;;;;8474:16;;8463:7;8428:5;:19;8434:12;:10;:12::i;:::-;8428:19;;;;;;;;;;;;;;;:32;;;:42;;;;:::i;:::-;:62;;8365:125;8344:248;;;;;;;;;;;;:::i;:::-;;;;;;;;;8680:22;:20;:22::i;:::-;8713:29;8792:7;8745:5;:19;8751:12;:10;:12::i;:::-;8745:19;;;;;;;;;;;;;;;:32;;;:54;;;;:::i;:::-;8713:86;;8814:21;:51;;;;8864:1;8839:21;:26;8814:51;8810:184;;;8881:36;8895:21;8881:13;:36::i;:::-;8810:184;;;8948:35;8961:21;8948:12;:35::i;:::-;8810:184;9039:21;9004:5;:19;9010:12;:10;:12::i;:::-;9004:19;;;;;;;;;;;;;;;:32;;:56;;;;9096:7;9070:22;;:33;;;;;;;:::i;:::-;;;;;;;;9114:48;9140:12;:10;:12::i;:::-;9154:7;9114:12;:25;;;;:48;;;;;:::i;:::-;9188:12;:10;:12::i;:::-;9178:32;;;9202:7;9178:32;;;;;;:::i;:::-;;;;;;;;8051:1166;7920:1297;;;:::o;6659:1255::-;6779:15;6760:34;;:15;:34;;6739:109;;;;;;;;;;;;:::i;:::-;;;;;;;;;6904:1;6879:22;;:26;6858:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;7014:25;;;;;;;;;;;6996:43;;:15;:43;6975:116;;;;;;;;;;;;:::i;:::-;;;;;;;;;7119:1;7109:7;:11;7101:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;7226:16;;7190:5;:19;7196:12;:10;:12::i;:::-;7190:19;;;;;;;;;;;;;;;:32;;;7180:7;:42;;;;:::i;:::-;:62;;7159:160;;;;;;;;;;;;:::i;:::-;;;;;;;;;7330:67;7360:12;:10;:12::i;:::-;7382:4;7389:7;7330:12;:29;;;;:67;;;;;;:::i;:::-;7485:22;:20;:22::i;:::-;7518:29;7597:7;7550:5;:19;7556:12;:10;:12::i;:::-;7550:19;;;;;;;;;;;;;;;:32;;;:54;;;;:::i;:::-;7518:86;;7619:21;7615:138;;;7656:20;7670:5;7656:13;:20::i;:::-;7615:138;;;7707:35;7720:21;7707:12;:35::i;:::-;7615:138;7798:21;7763:5;:19;7769:12;:10;:12::i;:::-;7763:19;;;;;;;;;;;;;;;:32;;:56;;;;7855:7;7829:22;;:33;;;;;;;:::i;:::-;;;;;;;;7885:12;:10;:12::i;:::-;7878:29;;;7899:7;7878:29;;;;;;:::i;:::-;;;;;;;;6729:1185;6659:1255;;:::o;588:104:12:-;646:7;676:1;672;:5;:13;;684:1;672:13;;;680:1;672:13;665:20;;588:104;;;;:::o;1667:3925::-;1779:14;2126:13;2198;2323:1;2319:6;2316:1;2313;2306:20;2359:1;2356;2352:9;2343:18;;2414:5;2410:2;2407:13;2399:5;2395:2;2391:14;2387:34;2378:43;;2278:157;2525:1;2516:5;:10;2512:75;;2561:11;2553:5;:19;;;;;:::i;:::-;;;2546:26;;;;;;2512:75;2711:5;2697:11;:19;2689:28;;;;;;2973:17;3108:11;3105:1;3102;3095:25;3082:38;;3236:5;3225:9;3222:20;3215:5;3211:32;3202:41;;3280:9;3273:5;3269:21;3260:30;;3611:12;3656:1;3642:11;3641:12;:16;3626:11;:32;3611:47;;3778:4;3765:11;3761:22;3746:37;;3870:4;3863:5;3859:16;3850:25;;4027:1;4020:4;4013;4010:1;4006:12;4002:23;3998:31;3990:39;;4126:4;4118:5;:12;4109:21;;;;4448:15;4486:1;4471:11;4467:1;:15;4466:21;4448:39;;4733:7;4719:11;:21;4715:1;:25;4704:36;;;;4802:7;4788:11;:21;4784:1;:25;4773:36;;;;4872:7;4858:11;:21;4854:1;:25;4843:36;;;;4942:7;4928:11;:21;4924:1;:25;4913:36;;;;5012:7;4998:11;:21;4994:1;:25;4983:36;;;;5083:7;5069:11;:21;5065:1;:25;5054:36;;;;5541:7;5533:5;:15;5524:24;;5562:13;;;;;1667:3925;;;;;;:::o;12957:818:13:-;13226:25;13253:18;13283:43;13374:34;13329:26;:79;;;;:::i;:::-;13283:125;;13419:20;13442:133;13467:35;13516:17;1044:4;13442:11;:133::i;:::-;13419:156;;13599:113;13624:12;13650:18;13682:20;13599:11;:113::i;:::-;13586:126;;13758:10;13743:12;:25;;;;:::i;:::-;13723:45;;13273:502;;12957:818;;;;;;;;:::o;3718:479:0:-;3806:22;3814:4;3820:7;3806;:22::i;:::-;3801:390;;3989:28;4009:7;3989:19;:28::i;:::-;4088:38;4116:4;4108:13;;4123:2;4088:19;:38::i;:::-;3896:252;;;;;;;;;:::i;:::-;;;;;;;;;;;;;3844:336;;;;;;;;;;;:::i;:::-;;;;;;;;3801:390;3718:479;;:::o;3747:706:6:-;4166:23;4192:69;4220:4;4192:69;;;;;;;;;;;;;;;;;4200:5;4192:27;;;;:69;;;;;:::i;:::-;4166:95;;4295:1;4275:10;:17;:21;4271:176;;;4370:10;4359:30;;;;;;;;;;;;:::i;:::-;4351:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;4271:176;3817:636;3747:706;;:::o;1945:106:2:-;2011:8;:6;:8::i;:::-;2003:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;1945:106::o;10567:811:13:-;10649:25;10688:18;10719:271;10762:5;:19;10768:12;:10;:12::i;:::-;10762:19;;;;;;;;;;;;;;;:49;;;10829:5;:19;10835:12;:10;:12::i;:::-;10829:19;;;;;;;;;;;;;;;:32;;;10879:25;;10922:17;;10957:19;;10719:25;:271::i;:::-;10635:355;;;;11001:20;11044:10;11024:17;:30;;;;:::i;:::-;11001:53;;11065:43;11111:110;11136:12;1044:4;11194:17;11111:11;:110::i;:::-;11065:156;;11336:35;11296:25;;:75;;;;:::i;:::-;11232:5;:19;11238:12;:10;:12::i;:::-;11232:19;;;;;;;;;;;;;;;:49;;:139;;;;10625:753;;;;10567:811;:::o;2102:149:9:-;2160:13;2192:52;2220:4;2204:22;;311:2;2192:52;;:11;:52::i;:::-;2185:59;;2102:149;;;:::o;1513:437::-;1588:13;1613:19;1658:1;1649:6;1645:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;1635:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1613:47;;1670:15;:6;1677:1;1670:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;1695;:6;1702:1;1695:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;1725:9;1750:1;1741:6;1737:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;1725:26;;1720:128;1757:1;1753;:5;1720:128;;;1791:8;1808:3;1800:5;:11;1791:21;;;;;;;:::i;:::-;;;;;1779:6;1786:1;1779:9;;;;;;;;:::i;:::-;;;;;:33;;;;;;;;;;;1836:1;1826:11;;;;;1760:3;;;;:::i;:::-;;;1720:128;;;;1874:1;1865:5;:10;1857:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;1936:6;1922:21;;;1513:437;;;;:::o;3873:223:7:-;4006:12;4037:52;4059:6;4067:4;4073:1;4076:12;4037:21;:52::i;:::-;4030:59;;3873:223;;;;;:::o;4960:446::-;5125:12;5182:5;5157:21;:30;;5149:81;;;;;;;;;;;;:::i;:::-;;;;;;;;;5241:12;5255:23;5282:6;:11;;5301:5;5308:4;5282:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5240:73;;;;5330:69;5357:6;5365:7;5374:10;5386:12;5330:26;:69::i;:::-;5323:76;;;;4960:446;;;;;;:::o;7466:628::-;7646:12;7674:7;7670:418;;;7722:1;7701:10;:17;:22;7697:286;;7916:18;7927:6;7916:10;:18::i;:::-;7908:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;7697:286;8003:10;7996:17;;;;7670:418;8044:33;8052:10;8064:12;8044:7;:33::i;:::-;7466:628;;;;;;;:::o;1175:320::-;1235:4;1487:1;1465:7;:19;;;:23;1458:30;;1175:320;;;:::o;8616:540::-;8795:1;8775:10;:17;:21;8771:379;;;9003:10;8997:17;9059:15;9046:10;9042:2;9038:19;9031:44;8771:379;9126:12;9119:20;;;;;;;;;;;:::i;:::-;;;;;;;;88:117:14;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:77::-;1555:7;1584:5;1573:16;;1518:77;;;:::o;1601:118::-;1688:24;1706:5;1688:24;:::i;:::-;1683:3;1676:37;1601:118;;:::o;1725:222::-;1818:4;1856:2;1845:9;1841:18;1833:26;;1869:71;1937:1;1926:9;1922:17;1913:6;1869:71;:::i;:::-;1725:222;;;;:::o;1953:122::-;2026:24;2044:5;2026:24;:::i;:::-;2019:5;2016:35;2006:63;;2065:1;2062;2055:12;2006:63;1953:122;:::o;2081:139::-;2127:5;2165:6;2152:20;2143:29;;2181:33;2208:5;2181:33;:::i;:::-;2081:139;;;;:::o;2226:329::-;2285:6;2334:2;2322:9;2313:7;2309:23;2305:32;2302:119;;;2340:79;;:::i;:::-;2302:119;2460:1;2485:53;2530:7;2521:6;2510:9;2506:22;2485:53;:::i;:::-;2475:63;;2431:117;2226:329;;;;:::o;2561:77::-;2598:7;2627:5;2616:16;;2561:77;;;:::o;2644:122::-;2717:24;2735:5;2717:24;:::i;:::-;2710:5;2707:35;2697:63;;2756:1;2753;2746:12;2697:63;2644:122;:::o;2772:139::-;2818:5;2856:6;2843:20;2834:29;;2872:33;2899:5;2872:33;:::i;:::-;2772:139;;;;:::o;2917:329::-;2976:6;3025:2;3013:9;3004:7;3000:23;2996:32;2993:119;;;3031:79;;:::i;:::-;2993:119;3151:1;3176:53;3221:7;3212:6;3201:9;3197:22;3176:53;:::i;:::-;3166:63;;3122:117;2917:329;;;;:::o;3252:118::-;3339:24;3357:5;3339:24;:::i;:::-;3334:3;3327:37;3252:118;;:::o;3376:222::-;3469:4;3507:2;3496:9;3492:18;3484:26;;3520:71;3588:1;3577:9;3573:17;3564:6;3520:71;:::i;:::-;3376:222;;;;:::o;3604:126::-;3641:7;3681:42;3674:5;3670:54;3659:65;;3604:126;;;:::o;3736:96::-;3773:7;3802:24;3820:5;3802:24;:::i;:::-;3791:35;;3736:96;;;:::o;3838:122::-;3911:24;3929:5;3911:24;:::i;:::-;3904:5;3901:35;3891:63;;3950:1;3947;3940:12;3891:63;3838:122;:::o;3966:139::-;4012:5;4050:6;4037:20;4028:29;;4066:33;4093:5;4066:33;:::i;:::-;3966:139;;;;:::o;4111:474::-;4179:6;4187;4236:2;4224:9;4215:7;4211:23;4207:32;4204:119;;;4242:79;;:::i;:::-;4204:119;4362:1;4387:53;4432:7;4423:6;4412:9;4408:22;4387:53;:::i;:::-;4377:63;;4333:117;4489:2;4515:53;4560:7;4551:6;4540:9;4536:22;4515:53;:::i;:::-;4505:63;;4460:118;4111:474;;;;;:::o;4591:::-;4659:6;4667;4716:2;4704:9;4695:7;4691:23;4687:32;4684:119;;;4722:79;;:::i;:::-;4684:119;4842:1;4867:53;4912:7;4903:6;4892:9;4888:22;4867:53;:::i;:::-;4857:63;;4813:117;4969:2;4995:53;5040:7;5031:6;5020:9;5016:22;4995:53;:::i;:::-;4985:63;;4940:118;4591:474;;;;;:::o;5071:60::-;5099:3;5120:5;5113:12;;5071:60;;;:::o;5137:142::-;5187:9;5220:53;5238:34;5247:24;5265:5;5247:24;:::i;:::-;5238:34;:::i;:::-;5220:53;:::i;:::-;5207:66;;5137:142;;;:::o;5285:126::-;5335:9;5368:37;5399:5;5368:37;:::i;:::-;5355:50;;5285:126;;;:::o;5417:140::-;5481:9;5514:37;5545:5;5514:37;:::i;:::-;5501:50;;5417:140;;;:::o;5563:159::-;5664:51;5709:5;5664:51;:::i;:::-;5659:3;5652:64;5563:159;;:::o;5728:250::-;5835:4;5873:2;5862:9;5858:18;5850:26;;5886:85;5968:1;5957:9;5953:17;5944:6;5886:85;:::i;:::-;5728:250;;;;:::o;5984:101::-;6020:7;6060:18;6053:5;6049:30;6038:41;;5984:101;;;:::o;6091:115::-;6176:23;6193:5;6176:23;:::i;:::-;6171:3;6164:36;6091:115;;:::o;6212:218::-;6303:4;6341:2;6330:9;6326:18;6318:26;;6354:69;6420:1;6409:9;6405:17;6396:6;6354:69;:::i;:::-;6212:218;;;;:::o;6436:110::-;6487:7;6516:24;6534:5;6516:24;:::i;:::-;6505:35;;6436:110;;;:::o;6552:150::-;6639:38;6671:5;6639:38;:::i;:::-;6632:5;6629:49;6619:77;;6692:1;6689;6682:12;6619:77;6552:150;:::o;6708:167::-;6768:5;6806:6;6793:20;6784:29;;6822:47;6863:5;6822:47;:::i;:::-;6708:167;;;;:::o;6881:502::-;6963:6;6971;7020:2;7008:9;6999:7;6995:23;6991:32;6988:119;;;7026:79;;:::i;:::-;6988:119;7146:1;7171:67;7230:7;7221:6;7210:9;7206:22;7171:67;:::i;:::-;7161:77;;7117:131;7287:2;7313:53;7358:7;7349:6;7338:9;7334:22;7313:53;:::i;:::-;7303:63;;7258:118;6881:502;;;;;:::o;7389:116::-;7459:21;7474:5;7459:21;:::i;:::-;7452:5;7449:32;7439:60;;7495:1;7492;7485:12;7439:60;7389:116;:::o;7511:133::-;7554:5;7592:6;7579:20;7570:29;;7608:30;7632:5;7608:30;:::i;:::-;7511:133;;;;:::o;7650:607::-;7721:6;7729;7737;7786:2;7774:9;7765:7;7761:23;7757:32;7754:119;;;7792:79;;:::i;:::-;7754:119;7912:1;7937:53;7982:7;7973:6;7962:9;7958:22;7937:53;:::i;:::-;7927:63;;7883:117;8039:2;8065:50;8107:7;8098:6;8087:9;8083:22;8065:50;:::i;:::-;8055:60;;8010:115;8164:2;8190:50;8232:7;8223:6;8212:9;8208:22;8190:50;:::i;:::-;8180:60;;8135:115;7650:607;;;;;:::o;8263:329::-;8322:6;8371:2;8359:9;8350:7;8346:23;8342:32;8339:119;;;8377:79;;:::i;:::-;8339:119;8497:1;8522:53;8567:7;8558:6;8547:9;8543:22;8522:53;:::i;:::-;8512:63;;8468:117;8263:329;;;;:::o;8598:332::-;8719:4;8757:2;8746:9;8742:18;8734:26;;8770:71;8838:1;8827:9;8823:17;8814:6;8770:71;:::i;:::-;8851:72;8919:2;8908:9;8904:18;8895:6;8851:72;:::i;:::-;8598:332;;;;;:::o;8936:468::-;9001:6;9009;9058:2;9046:9;9037:7;9033:23;9029:32;9026:119;;;9064:79;;:::i;:::-;9026:119;9184:1;9209:53;9254:7;9245:6;9234:9;9230:22;9209:53;:::i;:::-;9199:63;;9155:117;9311:2;9337:50;9379:7;9370:6;9359:9;9355:22;9337:50;:::i;:::-;9327:60;;9282:115;8936:468;;;;;:::o;9410:120::-;9482:23;9499:5;9482:23;:::i;:::-;9475:5;9472:34;9462:62;;9520:1;9517;9510:12;9462:62;9410:120;:::o;9536:137::-;9581:5;9619:6;9606:20;9597:29;;9635:32;9661:5;9635:32;:::i;:::-;9536:137;;;;:::o;9679:327::-;9737:6;9786:2;9774:9;9765:7;9761:23;9757:32;9754:119;;;9792:79;;:::i;:::-;9754:119;9912:1;9937:52;9981:7;9972:6;9961:9;9957:22;9937:52;:::i;:::-;9927:62;;9883:116;9679:327;;;;:::o;10012:169::-;10096:11;10130:6;10125:3;10118:19;10170:4;10165:3;10161:14;10146:29;;10012:169;;;;:::o;10187:220::-;10327:34;10323:1;10315:6;10311:14;10304:58;10396:3;10391:2;10383:6;10379:15;10372:28;10187:220;:::o;10413:366::-;10555:3;10576:67;10640:2;10635:3;10576:67;:::i;:::-;10569:74;;10652:93;10741:3;10652:93;:::i;:::-;10770:2;10765:3;10761:12;10754:19;;10413:366;;;:::o;10785:419::-;10951:4;10989:2;10978:9;10974:18;10966:26;;11038:9;11032:4;11028:20;11024:1;11013:9;11009:17;11002:47;11066:131;11192:4;11066:131;:::i;:::-;11058:139;;10785:419;;;:::o;11210:180::-;11258:77;11255:1;11248:88;11355:4;11352:1;11345:15;11379:4;11376:1;11369:15;11396:191;11436:3;11455:20;11473:1;11455:20;:::i;:::-;11450:25;;11489:20;11507:1;11489:20;:::i;:::-;11484:25;;11532:1;11529;11525:9;11518:16;;11553:3;11550:1;11547:10;11544:36;;;11560:18;;:::i;:::-;11544:36;11396:191;;;;:::o;11593:434::-;11738:4;11776:2;11765:9;11761:18;11753:26;;11789:71;11857:1;11846:9;11842:17;11833:6;11789:71;:::i;:::-;11870:70;11936:2;11925:9;11921:18;11912:6;11870:70;:::i;:::-;11950;12016:2;12005:9;12001:18;11992:6;11950:70;:::i;:::-;11593:434;;;;;;:::o;12033:234::-;12173:34;12169:1;12161:6;12157:14;12150:58;12242:17;12237:2;12229:6;12225:15;12218:42;12033:234;:::o;12273:366::-;12415:3;12436:67;12500:2;12495:3;12436:67;:::i;:::-;12429:74;;12512:93;12601:3;12512:93;:::i;:::-;12630:2;12625:3;12621:12;12614:19;;12273:366;;;:::o;12645:419::-;12811:4;12849:2;12838:9;12834:18;12826:26;;12898:9;12892:4;12888:20;12884:1;12873:9;12869:17;12862:47;12926:131;13052:4;12926:131;:::i;:::-;12918:139;;12645:419;;;:::o;13070:410::-;13110:7;13133:20;13151:1;13133:20;:::i;:::-;13128:25;;13167:20;13185:1;13167:20;:::i;:::-;13162:25;;13222:1;13219;13215:9;13244:30;13262:11;13244:30;:::i;:::-;13233:41;;13423:1;13414:7;13410:15;13407:1;13404:22;13384:1;13377:9;13357:83;13334:139;;13453:18;;:::i;:::-;13334:139;13118:362;13070:410;;;;:::o;13486:175::-;13626:27;13622:1;13614:6;13610:14;13603:51;13486:175;:::o;13667:366::-;13809:3;13830:67;13894:2;13889:3;13830:67;:::i;:::-;13823:74;;13906:93;13995:3;13906:93;:::i;:::-;14024:2;14019:3;14015:12;14008:19;;13667:366;;;:::o;14039:419::-;14205:4;14243:2;14232:9;14228:18;14220:26;;14292:9;14286:4;14282:20;14278:1;14267:9;14263:17;14256:47;14320:131;14446:4;14320:131;:::i;:::-;14312:139;;14039:419;;;:::o;14464:220::-;14604:34;14600:1;14592:6;14588:14;14581:58;14673:3;14668:2;14660:6;14656:15;14649:28;14464:220;:::o;14690:366::-;14832:3;14853:67;14917:2;14912:3;14853:67;:::i;:::-;14846:74;;14929:93;15018:3;14929:93;:::i;:::-;15047:2;15042:3;15038:12;15031:19;;14690:366;;;:::o;15062:419::-;15228:4;15266:2;15255:9;15251:18;15243:26;;15315:9;15309:4;15305:20;15301:1;15290:9;15286:17;15279:47;15343:131;15469:4;15343:131;:::i;:::-;15335:139;;15062:419;;;:::o;15487:182::-;15627:34;15623:1;15615:6;15611:14;15604:58;15487:182;:::o;15675:366::-;15817:3;15838:67;15902:2;15897:3;15838:67;:::i;:::-;15831:74;;15914:93;16003:3;15914:93;:::i;:::-;16032:2;16027:3;16023:12;16016:19;;15675:366;;;:::o;16047:419::-;16213:4;16251:2;16240:9;16236:18;16228:26;;16300:9;16294:4;16290:20;16286:1;16275:9;16271:17;16264:47;16328:131;16454:4;16328:131;:::i;:::-;16320:139;;16047:419;;;:::o;16472:118::-;16559:24;16577:5;16559:24;:::i;:::-;16554:3;16547:37;16472:118;;:::o;16596:222::-;16689:4;16727:2;16716:9;16712:18;16704:26;;16740:71;16808:1;16797:9;16793:17;16784:6;16740:71;:::i;:::-;16596:222;;;;:::o;16824:143::-;16881:5;16912:6;16906:13;16897:22;;16928:33;16955:5;16928:33;:::i;:::-;16824:143;;;;:::o;16973:351::-;17043:6;17092:2;17080:9;17071:7;17067:23;17063:32;17060:119;;;17098:79;;:::i;:::-;17060:119;17218:1;17243:64;17299:7;17290:6;17279:9;17275:22;17243:64;:::i;:::-;17233:74;;17189:128;16973:351;;;;:::o;17330:179::-;17470:31;17466:1;17458:6;17454:14;17447:55;17330:179;:::o;17515:366::-;17657:3;17678:67;17742:2;17737:3;17678:67;:::i;:::-;17671:74;;17754:93;17843:3;17754:93;:::i;:::-;17872:2;17867:3;17863:12;17856:19;;17515:366;;;:::o;17887:419::-;18053:4;18091:2;18080:9;18076:18;18068:26;;18140:9;18134:4;18130:20;18126:1;18115:9;18111:17;18104:47;18168:131;18294:4;18168:131;:::i;:::-;18160:139;;17887:419;;;:::o;18312:227::-;18452:34;18448:1;18440:6;18436:14;18429:58;18521:10;18516:2;18508:6;18504:15;18497:35;18312:227;:::o;18545:366::-;18687:3;18708:67;18772:2;18767:3;18708:67;:::i;:::-;18701:74;;18784:93;18873:3;18784:93;:::i;:::-;18902:2;18897:3;18893:12;18886:19;;18545:366;;;:::o;18917:419::-;19083:4;19121:2;19110:9;19106:18;19098:26;;19170:9;19164:4;19160:20;19156:1;19145:9;19141:17;19134:47;19198:131;19324:4;19198:131;:::i;:::-;19190:139;;18917:419;;;:::o;19342:194::-;19382:4;19402:20;19420:1;19402:20;:::i;:::-;19397:25;;19436:20;19454:1;19436:20;:::i;:::-;19431:25;;19480:1;19477;19473:9;19465:17;;19504:1;19498:4;19495:11;19492:37;;;19509:18;;:::i;:::-;19492:37;19342:194;;;;:::o;19542:232::-;19682:34;19678:1;19670:6;19666:14;19659:58;19751:15;19746:2;19738:6;19734:15;19727:40;19542:232;:::o;19780:366::-;19922:3;19943:67;20007:2;20002:3;19943:67;:::i;:::-;19936:74;;20019:93;20108:3;20019:93;:::i;:::-;20137:2;20132:3;20128:12;20121:19;;19780:366;;;:::o;20152:419::-;20318:4;20356:2;20345:9;20341:18;20333:26;;20405:9;20399:4;20395:20;20391:1;20380:9;20376:17;20369:47;20433:131;20559:4;20433:131;:::i;:::-;20425:139;;20152:419;;;:::o;20577:221::-;20717:34;20713:1;20705:6;20701:14;20694:58;20786:4;20781:2;20773:6;20769:15;20762:29;20577:221;:::o;20804:366::-;20946:3;20967:67;21031:2;21026:3;20967:67;:::i;:::-;20960:74;;21043:93;21132:3;21043:93;:::i;:::-;21161:2;21156:3;21152:12;21145:19;;20804:366;;;:::o;21176:419::-;21342:4;21380:2;21369:9;21365:18;21357:26;;21429:9;21423:4;21419:20;21415:1;21404:9;21400:17;21393:47;21457:131;21583:4;21457:131;:::i;:::-;21449:139;;21176:419;;;:::o;21601:225::-;21741:34;21737:1;21729:6;21725:14;21718:58;21810:8;21805:2;21797:6;21793:15;21786:33;21601:225;:::o;21832:366::-;21974:3;21995:67;22059:2;22054:3;21995:67;:::i;:::-;21988:74;;22071:93;22160:3;22071:93;:::i;:::-;22189:2;22184:3;22180:12;22173:19;;21832:366;;;:::o;22204:419::-;22370:4;22408:2;22397:9;22393:18;22385:26;;22457:9;22451:4;22447:20;22443:1;22432:9;22428:17;22421:47;22485:131;22611:4;22485:131;:::i;:::-;22477:139;;22204:419;;;:::o;22629:221::-;22769:34;22765:1;22757:6;22753:14;22746:58;22838:4;22833:2;22825:6;22821:15;22814:29;22629:221;:::o;22856:366::-;22998:3;23019:67;23083:2;23078:3;23019:67;:::i;:::-;23012:74;;23095:93;23184:3;23095:93;:::i;:::-;23213:2;23208:3;23204:12;23197:19;;22856:366;;;:::o;23228:419::-;23394:4;23432:2;23421:9;23417:18;23409:26;;23481:9;23475:4;23471:20;23467:1;23456:9;23452:17;23445:47;23509:131;23635:4;23509:131;:::i;:::-;23501:139;;23228:419;;;:::o;23653:244::-;23793:34;23789:1;23781:6;23777:14;23770:58;23862:27;23857:2;23849:6;23845:15;23838:52;23653:244;:::o;23903:366::-;24045:3;24066:67;24130:2;24125:3;24066:67;:::i;:::-;24059:74;;24142:93;24231:3;24142:93;:::i;:::-;24260:2;24255:3;24251:12;24244:19;;23903:366;;;:::o;24275:419::-;24441:4;24479:2;24468:9;24464:18;24456:26;;24528:9;24522:4;24518:20;24514:1;24503:9;24499:17;24492:47;24556:131;24682:4;24556:131;:::i;:::-;24548:139;;24275:419;;;:::o;24700:178::-;24840:30;24836:1;24828:6;24824:14;24817:54;24700:178;:::o;24884:366::-;25026:3;25047:67;25111:2;25106:3;25047:67;:::i;:::-;25040:74;;25123:93;25212:3;25123:93;:::i;:::-;25241:2;25236:3;25232:12;25225:19;;24884:366;;;:::o;25256:419::-;25422:4;25460:2;25449:9;25445:18;25437:26;;25509:9;25503:4;25499:20;25495:1;25484:9;25480:17;25473:47;25537:131;25663:4;25537:131;:::i;:::-;25529:139;;25256:419;;;:::o;25681:208::-;25720:4;25740:19;25757:1;25740:19;:::i;:::-;25735:24;;25773:19;25790:1;25773:19;:::i;:::-;25768:24;;25816:1;25813;25809:9;25801:17;;25840:18;25834:4;25831:28;25828:54;;;25862:18;;:::i;:::-;25828:54;25681:208;;;;:::o;25895:247::-;26035:34;26031:1;26023:6;26019:14;26012:58;26104:30;26099:2;26091:6;26087:15;26080:55;25895:247;:::o;26148:366::-;26290:3;26311:67;26375:2;26370:3;26311:67;:::i;:::-;26304:74;;26387:93;26476:3;26387:93;:::i;:::-;26505:2;26500:3;26496:12;26489:19;;26148:366;;;:::o;26520:419::-;26686:4;26724:2;26713:9;26709:18;26701:26;;26773:9;26767:4;26763:20;26759:1;26748:9;26744:17;26737:47;26801:131;26927:4;26801:131;:::i;:::-;26793:139;;26520:419;;;:::o;26945:181::-;27085:33;27081:1;27073:6;27069:14;27062:57;26945:181;:::o;27132:366::-;27274:3;27295:67;27359:2;27354:3;27295:67;:::i;:::-;27288:74;;27371:93;27460:3;27371:93;:::i;:::-;27489:2;27484:3;27480:12;27473:19;;27132:366;;;:::o;27504:419::-;27670:4;27708:2;27697:9;27693:18;27685:26;;27757:9;27751:4;27747:20;27743:1;27732:9;27728:17;27721:47;27785:131;27911:4;27785:131;:::i;:::-;27777:139;;27504:419;;;:::o;27929:442::-;28078:4;28116:2;28105:9;28101:18;28093:26;;28129:71;28197:1;28186:9;28182:17;28173:6;28129:71;:::i;:::-;28210:72;28278:2;28267:9;28263:18;28254:6;28210:72;:::i;:::-;28292;28360:2;28349:9;28345:18;28336:6;28292:72;:::i;:::-;27929:442;;;;;;:::o;28377:166::-;28517:18;28513:1;28505:6;28501:14;28494:42;28377:166;:::o;28549:366::-;28691:3;28712:67;28776:2;28771:3;28712:67;:::i;:::-;28705:74;;28788:93;28877:3;28788:93;:::i;:::-;28906:2;28901:3;28897:12;28890:19;;28549:366;;;:::o;28921:419::-;29087:4;29125:2;29114:9;29110:18;29102:26;;29174:9;29168:4;29164:20;29160:1;29149:9;29145:17;29138:47;29202:131;29328:4;29202:131;:::i;:::-;29194:139;;28921:419;;;:::o;29346:177::-;29486:29;29482:1;29474:6;29470:14;29463:53;29346:177;:::o;29529:366::-;29671:3;29692:67;29756:2;29751:3;29692:67;:::i;:::-;29685:74;;29768:93;29857:3;29768:93;:::i;:::-;29886:2;29881:3;29877:12;29870:19;;29529:366;;;:::o;29901:419::-;30067:4;30105:2;30094:9;30090:18;30082:26;;30154:9;30148:4;30144:20;30140:1;30129:9;30125:17;30118:47;30182:131;30308:4;30182:131;:::i;:::-;30174:139;;29901:419;;;:::o;30326:332::-;30447:4;30485:2;30474:9;30470:18;30462:26;;30498:71;30566:1;30555:9;30551:17;30542:6;30498:71;:::i;:::-;30579:72;30647:2;30636:9;30632:18;30623:6;30579:72;:::i;:::-;30326:332;;;;;:::o;30664:171::-;30804:23;30800:1;30792:6;30788:14;30781:47;30664:171;:::o;30841:366::-;30983:3;31004:67;31068:2;31063:3;31004:67;:::i;:::-;30997:74;;31080:93;31169:3;31080:93;:::i;:::-;31198:2;31193:3;31189:12;31182:19;;30841:366;;;:::o;31213:419::-;31379:4;31417:2;31406:9;31402:18;31394:26;;31466:9;31460:4;31456:20;31452:1;31441:9;31437:17;31430:47;31494:131;31620:4;31494:131;:::i;:::-;31486:139;;31213:419;;;:::o;31638:228::-;31778:34;31774:1;31766:6;31762:14;31755:58;31847:11;31842:2;31834:6;31830:15;31823:36;31638:228;:::o;31872:366::-;32014:3;32035:67;32099:2;32094:3;32035:67;:::i;:::-;32028:74;;32111:93;32200:3;32111:93;:::i;:::-;32229:2;32224:3;32220:12;32213:19;;31872:366;;;:::o;32244:419::-;32410:4;32448:2;32437:9;32433:18;32425:26;;32497:9;32491:4;32487:20;32483:1;32472:9;32468:17;32461:47;32525:131;32651:4;32525:131;:::i;:::-;32517:139;;32244:419;;;:::o;32669:177::-;32809:29;32805:1;32797:6;32793:14;32786:53;32669:177;:::o;32852:366::-;32994:3;33015:67;33079:2;33074:3;33015:67;:::i;:::-;33008:74;;33091:93;33180:3;33091:93;:::i;:::-;33209:2;33204:3;33200:12;33193:19;;32852:366;;;:::o;33224:419::-;33390:4;33428:2;33417:9;33413:18;33405:26;;33477:9;33471:4;33467:20;33463:1;33452:9;33448:17;33441:47;33505:131;33631:4;33505:131;:::i;:::-;33497:139;;33224:419;;;:::o;33649:300::-;33789:34;33785:1;33777:6;33773:14;33766:58;33858:34;33853:2;33845:6;33841:15;33834:59;33927:14;33922:2;33914:6;33910:15;33903:39;33649:300;:::o;33955:366::-;34097:3;34118:67;34182:2;34177:3;34118:67;:::i;:::-;34111:74;;34194:93;34283:3;34194:93;:::i;:::-;34312:2;34307:3;34303:12;34296:19;;33955:366;;;:::o;34327:419::-;34493:4;34531:2;34520:9;34516:18;34508:26;;34580:9;34574:4;34570:20;34566:1;34555:9;34551:17;34544:47;34608:131;34734:4;34608:131;:::i;:::-;34600:139;;34327:419;;;:::o;34752:221::-;34892:34;34888:1;34880:6;34876:14;34869:58;34961:4;34956:2;34948:6;34944:15;34937:29;34752:221;:::o;34979:366::-;35121:3;35142:67;35206:2;35201:3;35142:67;:::i;:::-;35135:74;;35218:93;35307:3;35218:93;:::i;:::-;35336:2;35331:3;35327:12;35320:19;;34979:366;;;:::o;35351:419::-;35517:4;35555:2;35544:9;35540:18;35532:26;;35604:9;35598:4;35594:20;35590:1;35579:9;35575:17;35568:47;35632:131;35758:4;35632:131;:::i;:::-;35624:139;;35351:419;;;:::o;35776:176::-;35916:28;35912:1;35904:6;35900:14;35893:52;35776:176;:::o;35958:366::-;36100:3;36121:67;36185:2;36180:3;36121:67;:::i;:::-;36114:74;;36197:93;36286:3;36197:93;:::i;:::-;36315:2;36310:3;36306:12;36299:19;;35958:366;;;:::o;36330:419::-;36496:4;36534:2;36523:9;36519:18;36511:26;;36583:9;36577:4;36573:20;36569:1;36558:9;36554:17;36547:47;36611:131;36737:4;36611:131;:::i;:::-;36603:139;;36330:419;;;:::o;36755:174::-;36895:26;36891:1;36883:6;36879:14;36872:50;36755:174;:::o;36935:366::-;37077:3;37098:67;37162:2;37157:3;37098:67;:::i;:::-;37091:74;;37174:93;37263:3;37174:93;:::i;:::-;37292:2;37287:3;37283:12;37276:19;;36935:366;;;:::o;37307:419::-;37473:4;37511:2;37500:9;37496:18;37488:26;;37560:9;37554:4;37550:20;37546:1;37535:9;37531:17;37524:47;37588:131;37714:4;37588:131;:::i;:::-;37580:139;;37307:419;;;:::o;37732:238::-;37872:34;37868:1;37860:6;37856:14;37849:58;37941:21;37936:2;37928:6;37924:15;37917:46;37732:238;:::o;37976:366::-;38118:3;38139:67;38203:2;38198:3;38139:67;:::i;:::-;38132:74;;38215:93;38304:3;38215:93;:::i;:::-;38333:2;38328:3;38324:12;38317:19;;37976:366;;;:::o;38348:419::-;38514:4;38552:2;38541:9;38537:18;38529:26;;38601:9;38595:4;38591:20;38587:1;38576:9;38572:17;38565:47;38629:131;38755:4;38629:131;:::i;:::-;38621:139;;38348:419;;;:::o;38773:180::-;38821:77;38818:1;38811:88;38918:4;38915:1;38908:15;38942:4;38939:1;38932:15;38959:148;39061:11;39098:3;39083:18;;38959:148;;;;:::o;39113:173::-;39253:25;39249:1;39241:6;39237:14;39230:49;39113:173;:::o;39292:402::-;39452:3;39473:85;39555:2;39550:3;39473:85;:::i;:::-;39466:92;;39567:93;39656:3;39567:93;:::i;:::-;39685:2;39680:3;39676:12;39669:19;;39292:402;;;:::o;39700:99::-;39752:6;39786:5;39780:12;39770:22;;39700:99;;;:::o;39805:246::-;39886:1;39896:113;39910:6;39907:1;39904:13;39896:113;;;39995:1;39990:3;39986:11;39980:18;39976:1;39971:3;39967:11;39960:39;39932:2;39929:1;39925:10;39920:15;;39896:113;;;40043:1;40034:6;40029:3;40025:16;40018:27;39867:184;39805:246;;;:::o;40057:390::-;40163:3;40191:39;40224:5;40191:39;:::i;:::-;40246:89;40328:6;40323:3;40246:89;:::i;:::-;40239:96;;40344:65;40402:6;40397:3;40390:4;40383:5;40379:16;40344:65;:::i;:::-;40434:6;40429:3;40425:16;40418:23;;40167:280;40057:390;;;;:::o;40453:167::-;40593:19;40589:1;40581:6;40577:14;40570:43;40453:167;:::o;40626:402::-;40786:3;40807:85;40889:2;40884:3;40807:85;:::i;:::-;40800:92;;40901:93;40990:3;40901:93;:::i;:::-;41019:2;41014:3;41010:12;41003:19;;40626:402;;;:::o;41034:967::-;41416:3;41438:148;41582:3;41438:148;:::i;:::-;41431:155;;41603:95;41694:3;41685:6;41603:95;:::i;:::-;41596:102;;41715:148;41859:3;41715:148;:::i;:::-;41708:155;;41880:95;41971:3;41962:6;41880:95;:::i;:::-;41873:102;;41992:3;41985:10;;41034:967;;;;;:::o;42007:102::-;42048:6;42099:2;42095:7;42090:2;42083:5;42079:14;42075:28;42065:38;;42007:102;;;:::o;42115:377::-;42203:3;42231:39;42264:5;42231:39;:::i;:::-;42286:71;42350:6;42345:3;42286:71;:::i;:::-;42279:78;;42366:65;42424:6;42419:3;42412:4;42405:5;42401:16;42366:65;:::i;:::-;42456:29;42478:6;42456:29;:::i;:::-;42451:3;42447:39;42440:46;;42207:285;42115:377;;;;:::o;42498:313::-;42611:4;42649:2;42638:9;42634:18;42626:26;;42698:9;42692:4;42688:20;42684:1;42673:9;42669:17;42662:47;42726:78;42799:4;42790:6;42726:78;:::i;:::-;42718:86;;42498:313;;;;:::o;42817:137::-;42871:5;42902:6;42896:13;42887:22;;42918:30;42942:5;42918:30;:::i;:::-;42817:137;;;;:::o;42960:345::-;43027:6;43076:2;43064:9;43055:7;43051:23;43047:32;43044:119;;;43082:79;;:::i;:::-;43044:119;43202:1;43227:61;43280:7;43271:6;43260:9;43256:22;43227:61;:::i;:::-;43217:71;;43173:125;42960:345;;;;:::o;43311:229::-;43451:34;43447:1;43439:6;43435:14;43428:58;43520:12;43515:2;43507:6;43503:15;43496:37;43311:229;:::o;43546:366::-;43688:3;43709:67;43773:2;43768:3;43709:67;:::i;:::-;43702:74;;43785:93;43874:3;43785:93;:::i;:::-;43903:2;43898:3;43894:12;43887:19;;43546:366;;;:::o;43918:419::-;44084:4;44122:2;44111:9;44107:18;44099:26;;44171:9;44165:4;44161:20;44157:1;44146:9;44142:17;44135:47;44199:131;44325:4;44199:131;:::i;:::-;44191:139;;43918:419;;;:::o;44343:170::-;44483:22;44479:1;44471:6;44467:14;44460:46;44343:170;:::o;44519:366::-;44661:3;44682:67;44746:2;44741:3;44682:67;:::i;:::-;44675:74;;44758:93;44847:3;44758:93;:::i;:::-;44876:2;44871:3;44867:12;44860:19;;44519:366;;;:::o;44891:419::-;45057:4;45095:2;45084:9;45080:18;45072:26;;45144:9;45138:4;45134:20;45130:1;45119:9;45115:17;45108:47;45172:131;45298:4;45172:131;:::i;:::-;45164:139;;44891:419;;;:::o;45316:180::-;45364:77;45361:1;45354:88;45461:4;45458:1;45451:15;45485:4;45482:1;45475:15;45502:180;45550:77;45547:1;45540:88;45647:4;45644:1;45637:15;45671:4;45668:1;45661:15;45688:171;45727:3;45750:24;45768:5;45750:24;:::i;:::-;45741:33;;45796:4;45789:5;45786:15;45783:41;;45804:18;;:::i;:::-;45783:41;45851:1;45844:5;45840:13;45833:20;;45688:171;;;:::o;45865:182::-;46005:34;46001:1;45993:6;45989:14;45982:58;45865:182;:::o;46053:366::-;46195:3;46216:67;46280:2;46275:3;46216:67;:::i;:::-;46209:74;;46292:93;46381:3;46292:93;:::i;:::-;46410:2;46405:3;46401:12;46394:19;;46053:366;;;:::o;46425:419::-;46591:4;46629:2;46618:9;46614:18;46606:26;;46678:9;46672:4;46668:20;46664:1;46653:9;46649:17;46642:47;46706:131;46832:4;46706:131;:::i;:::-;46698:139;;46425:419;;;:::o;46850:225::-;46990:34;46986:1;46978:6;46974:14;46967:58;47059:8;47054:2;47046:6;47042:15;47035:33;46850:225;:::o;47081:366::-;47223:3;47244:67;47308:2;47303:3;47244:67;:::i;:::-;47237:74;;47320:93;47409:3;47320:93;:::i;:::-;47438:2;47433:3;47429:12;47422:19;;47081:366;;;:::o;47453:419::-;47619:4;47657:2;47646:9;47642:18;47634:26;;47706:9;47700:4;47696:20;47692:1;47681:9;47677:17;47670:47;47734:131;47860:4;47734:131;:::i;:::-;47726:139;;47453:419;;;:::o;47878:98::-;47929:6;47963:5;47957:12;47947:22;;47878:98;;;:::o;47982:147::-;48083:11;48120:3;48105:18;;47982:147;;;;:::o;48135:386::-;48239:3;48267:38;48299:5;48267:38;:::i;:::-;48321:88;48402:6;48397:3;48321:88;:::i;:::-;48314:95;;48418:65;48476:6;48471:3;48464:4;48457:5;48453:16;48418:65;:::i;:::-;48508:6;48503:3;48499:16;48492:23;;48243:278;48135:386;;;;:::o;48527:271::-;48657:3;48679:93;48768:3;48759:6;48679:93;:::i;:::-;48672:100;;48789:3;48782:10;;48527:271;;;;:::o;48804:179::-;48944:31;48940:1;48932:6;48928:14;48921:55;48804:179;:::o;48989:366::-;49131:3;49152:67;49216:2;49211:3;49152:67;:::i;:::-;49145:74;;49228:93;49317:3;49228:93;:::i;:::-;49346:2;49341:3;49337:12;49330:19;;48989:366;;;:::o;49361:419::-;49527:4;49565:2;49554:9;49550:18;49542:26;;49614:9;49608:4;49604:20;49600:1;49589:9;49585:17;49578:47;49642:131;49768:4;49642:131;:::i;:::-;49634:139;;49361:419;;;:::o
Swarm Source
ipfs://bc9c2003d2e09db21d5df4bc722aa9ebcdd59632b8474e96b57bf93a82ad0f8a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.