More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 148 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Get Reward2 | 22032853 | 7 days ago | IN | 0 ETH | 0.00032054 | ||||
Stake Locked | 22032847 | 7 days ago | IN | 0 ETH | 0.00038229 | ||||
Withdraw Locked | 22019160 | 9 days ago | IN | 0 ETH | 0.00166769 | ||||
Get Reward2 | 22019156 | 9 days ago | IN | 0 ETH | 0.0015633 | ||||
Get Reward2 | 21938196 | 21 days ago | IN | 0 ETH | 0.00074197 | ||||
Withdraw Locked | 21906795 | 25 days ago | IN | 0 ETH | 0.00040675 | ||||
Get Reward2 | 21884390 | 28 days ago | IN | 0 ETH | 0.00048343 | ||||
Get Reward2 | 21847633 | 33 days ago | IN | 0 ETH | 0.00043012 | ||||
Withdraw Locked | 21838980 | 35 days ago | IN | 0 ETH | 0.00204447 | ||||
Withdraw Locked | 21838975 | 35 days ago | IN | 0 ETH | 0.00190738 | ||||
Withdraw Locked | 21838973 | 35 days ago | IN | 0 ETH | 0.00214463 | ||||
Get Reward2 | 21835455 | 35 days ago | IN | 0 ETH | 0.00056309 | ||||
Get Reward2 | 21817314 | 38 days ago | IN | 0 ETH | 0.00107054 | ||||
Get Reward2 | 21785611 | 42 days ago | IN | 0 ETH | 0.00064862 | ||||
Withdraw Locked | 21757953 | 46 days ago | IN | 0 ETH | 0.00161766 | ||||
Get Reward2 | 21713169 | 52 days ago | IN | 0 ETH | 0.00288012 | ||||
Get Reward2 | 21641691 | 62 days ago | IN | 0 ETH | 0.00178531 | ||||
Stake Locked | 21641691 | 62 days ago | IN | 0 ETH | 0.00272625 | ||||
Stake Locked | 21637309 | 63 days ago | IN | 0 ETH | 0.00721786 | ||||
Stake Locked | 21637282 | 63 days ago | IN | 0 ETH | 0.00713 | ||||
Get Reward2 | 21635503 | 63 days ago | IN | 0 ETH | 0.00166107 | ||||
Get Reward2 | 21621722 | 65 days ago | IN | 0 ETH | 0.00152544 | ||||
Stake Locked | 21621718 | 65 days ago | IN | 0 ETH | 0.00254086 | ||||
Stake Locked | 21617106 | 66 days ago | IN | 0 ETH | 0.00430717 | ||||
Get Reward2 | 21595674 | 68 days ago | IN | 0 ETH | 0.00285231 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FraxUnifiedFarm_ERC20_Other
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-06-02 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.19.4 https://hardhat.org // File contracts/Common/Context.sol // Original license: SPDX_License_Identifier: MIT /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File contracts/Math/SafeMath.sol // Original license: SPDX_License_Identifier: MIT /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File contracts/ERC20/IERC20.sol // Original license: SPDX_License_Identifier: MIT /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File contracts/Misc_AMOs/morpho/IMetaMorpho.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface IMetaMorpho { struct MarketParams { address loanToken; address collateralToken; address oracle; address irm; uint256 lltv; } struct MarketAllocation { /// @notice The market to allocate. MarketParams marketParams; /// @notice The amount of assets to allocate. uint256 assets; } function DECIMALS_OFFSET ( ) external view returns ( uint8 ); function DOMAIN_SEPARATOR ( ) external view returns ( bytes32 ); function MORPHO ( ) external view returns ( address ); function acceptCap ( MarketParams memory marketParams ) external; function acceptGuardian ( ) external; function acceptOwnership ( ) external; function acceptTimelock ( ) external; function allowance ( address owner, address spender ) external view returns ( uint256 ); function approve ( address spender, uint256 value ) external returns ( bool ); function asset ( ) external view returns ( address ); function balanceOf ( address account ) external view returns ( uint256 ); function config ( bytes32 ) external view returns ( uint184 cap, bool enabled, uint64 removableAt ); function convertToAssets ( uint256 shares ) external view returns ( uint256 ); function convertToShares ( uint256 assets ) external view returns ( uint256 ); function curator ( ) external view returns ( address ); function decimals ( ) external view returns ( uint8 ); function deposit ( uint256 assets, address receiver ) external returns ( uint256 shares ); function eip712Domain ( ) external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); function fee ( ) external view returns ( uint96 ); function feeRecipient ( ) external view returns ( address ); function guardian ( ) external view returns ( address ); function isAllocator ( address ) external view returns ( bool ); function lastTotalAssets ( ) external view returns ( uint256 ); function maxDeposit ( address ) external view returns ( uint256 ); function maxMint ( address ) external view returns ( uint256 ); function maxRedeem ( address owner ) external view returns ( uint256 ); function maxWithdraw ( address owner ) external view returns ( uint256 assets ); function mint ( uint256 shares, address receiver ) external returns ( uint256 assets ); function multicall ( bytes[] memory data ) external returns ( bytes[] memory results ); function name ( ) external view returns ( string memory ); function nonces ( address owner ) external view returns ( uint256 ); function owner ( ) external view returns ( address ); function pendingCap ( bytes32 ) external view returns ( uint192 value, uint64 validAt ); function pendingGuardian ( ) external view returns ( address value, uint64 validAt ); function pendingOwner ( ) external view returns ( address ); function pendingTimelock ( ) external view returns ( uint192 value, uint64 validAt ); function permit ( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function previewDeposit ( uint256 assets ) external view returns ( uint256 ); function previewMint ( uint256 shares ) external view returns ( uint256 ); function previewRedeem ( uint256 shares ) external view returns ( uint256 ); function previewWithdraw ( uint256 assets ) external view returns ( uint256 ); function reallocate ( MarketAllocation[] memory allocations ) external; function redeem ( uint256 shares, address receiver, address owner ) external returns ( uint256 assets ); function renounceOwnership ( ) external; function revokePendingCap ( bytes32 id ) external; function revokePendingGuardian ( ) external; function revokePendingMarketRemoval ( bytes32 id ) external; function revokePendingTimelock ( ) external; function setCurator ( address newCurator ) external; function setFee ( uint256 newFee ) external; function setFeeRecipient ( address newFeeRecipient ) external; function setIsAllocator ( address newAllocator, bool newIsAllocator ) external; function setSkimRecipient ( address newSkimRecipient ) external; function setSupplyQueue ( bytes32[] memory newSupplyQueue ) external; function skim ( address token ) external; function skimRecipient ( ) external view returns ( address ); function submitCap ( MarketParams memory marketParams, uint256 newSupplyCap ) external; function submitGuardian ( address newGuardian ) external; function submitMarketRemoval ( MarketParams memory marketParams ) external; function submitTimelock ( uint256 newTimelock ) external; function supplyQueue ( uint256 ) external view returns ( bytes32 ); function supplyQueueLength ( ) external view returns ( uint256 ); function symbol ( ) external view returns ( string memory ); function timelock ( ) external view returns ( uint256 ); function totalAssets ( ) external view returns ( uint256 assets ); function totalSupply ( ) external view returns ( uint256 ); function transfer ( address to, uint256 value ) external returns ( bool ); function transferFrom ( address from, address to, uint256 value ) external returns ( bool ); function transferOwnership ( address newOwner ) external; function updateWithdrawQueue ( uint256[] memory indexes ) external; function withdraw ( uint256 assets, address receiver, address owner ) external returns ( uint256 shares ); function withdrawQueue ( uint256 ) external view returns ( bytes32 ); function withdrawQueueLength ( ) external view returns ( uint256 ); } // File contracts/Curve/IFraxGaugeController.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // https://github.com/swervefi/swerve/edit/master/packages/swerve-contracts/interfaces/IGaugeController.sol interface IFraxGaugeController { struct Point { uint256 bias; uint256 slope; } struct VotedSlope { uint256 slope; uint256 power; uint256 end; } // Public variables function admin() external view returns (address); function future_admin() external view returns (address); function token() external view returns (address); function voting_escrow() external view returns (address); function n_gauge_types() external view returns (int128); function n_gauges() external view returns (int128); function gauge_type_names(int128) external view returns (string memory); function gauges(uint256) external view returns (address); function vote_user_slopes(address, address) external view returns (VotedSlope memory); function vote_user_power(address) external view returns (uint256); function last_user_vote(address, address) external view returns (uint256); function points_weight(address, uint256) external view returns (Point memory); function time_weight(address) external view returns (uint256); function points_sum(int128, uint256) external view returns (Point memory); function time_sum(uint256) external view returns (uint256); function points_total(uint256) external view returns (uint256); function time_total() external view returns (uint256); function points_type_weight(int128, uint256) external view returns (uint256); function time_type_weight(uint256) external view returns (uint256); // Getter functions function gauge_types(address) external view returns (int128); function gauge_relative_weight(address) external view returns (uint256); function gauge_relative_weight(address, uint256) external view returns (uint256); function get_gauge_weight(address) external view returns (uint256); function get_type_weight(int128) external view returns (uint256); function get_total_weight() external view returns (uint256); function get_weights_sum_per_type(int128) external view returns (uint256); // External functions function commit_transfer_ownership(address) external; function apply_transfer_ownership() external; function add_gauge( address, int128, uint256 ) external; function checkpoint() external; function checkpoint_gauge(address) external; function global_emission_rate() external view returns (uint256); function gauge_relative_weight_write(address) external returns (uint256); function gauge_relative_weight_write(address, uint256) external returns (uint256); function add_type(string memory, uint256) external; function change_type_weight(int128, uint256) external; function change_gauge_weight(address, uint256) external; function change_global_emission_rate(uint256) external; function vote_for_gauge_weights(address, uint256) external; } // File contracts/Curve/IFraxGaugeFXSRewardsDistributor.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface IFraxGaugeFXSRewardsDistributor { function acceptOwnership() external; function curator_address() external view returns(address); function currentReward(address gauge_address) external view returns(uint256 reward_amount); function distributeReward(address gauge_address) external returns(uint256 weeks_elapsed, uint256 reward_tally); function distributionsOn() external view returns(bool); function gauge_whitelist(address) external view returns(bool); function is_middleman(address) external view returns(bool); function last_time_gauge_paid(address) external view returns(uint256); function nominateNewOwner(address _owner) external; function nominatedOwner() external view returns(address); function owner() external view returns(address); function recoverERC20(address tokenAddress, uint256 tokenAmount) external; function setCurator(address _new_curator_address) external; function setGaugeController(address _gauge_controller_address) external; function setGaugeState(address _gauge_address, bool _is_middleman, bool _is_active) external; function setTimelock(address _new_timelock) external; function timelock_address() external view returns(address); function toggleDistributions() external; } // File contracts/Curve/IveFXS.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface IveFXS { struct LockedBalance { int128 amount; uint256 end; } function commit_transfer_ownership(address addr) external; function apply_transfer_ownership() external; function commit_smart_wallet_checker(address addr) external; function apply_smart_wallet_checker() external; function toggleEmergencyUnlock() external; function recoverERC20(address token_addr, uint256 amount) external; function get_last_user_slope(address addr) external view returns (int128); function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256); function locked__end(address _addr) external view returns (uint256); function checkpoint() external; function deposit_for(address _addr, uint256 _value) external; function create_lock(uint256 _value, uint256 _unlock_time) external; function increase_amount(uint256 _value) external; function increase_unlock_time(uint256 _unlock_time) external; function withdraw() external; function balanceOf(address addr) external view returns (uint256); function balanceOf(address addr, uint256 _t) external view returns (uint256); function balanceOfAt(address addr, uint256 _block) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupply(uint256 t) external view returns (uint256); function totalSupplyAt(uint256 _block) external view returns (uint256); function totalFXSSupply() external view returns (uint256); function totalFXSSupplyAt(uint256 _block) external view returns (uint256); function changeController(address _newController) external; function token() external view returns (address); function supply() external view returns (uint256); function locked(address addr) external view returns (LockedBalance memory); function epoch() external view returns (uint256); function point_history(uint256 arg0) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_history(address arg0, uint256 arg1) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_epoch(address arg0) external view returns (uint256); function slope_changes(uint256 arg0) external view returns (int128); function controller() external view returns (address); function transfersEnabled() external view returns (bool); function emergencyUnlockActive() external view returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function version() external view returns (string memory); function decimals() external view returns (uint256); function future_smart_wallet_checker() external view returns (address); function smart_wallet_checker() external view returns (address); function admin() external view returns (address); function future_admin() external view returns (address); } // File contracts/Math/Math.sol // Original license: SPDX_License_Identifier: MIT /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } // File contracts/Misc_AMOs/convex/IConvexBaseRewardPool.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later interface IConvexBaseRewardPool { function addExtraReward(address _reward) external returns (bool); function balanceOf(address account) external view returns (uint256); function clearExtraRewards() external; function currentRewards() external view returns (uint256); function donate(uint256 _amount) external returns (bool); function duration() external view returns (uint256); function earned(address account) external view returns (uint256); function extraRewards(uint256) external view returns (address); function extraRewardsLength() external view returns (uint256); function getReward() external returns (bool); function getReward(address _account, bool _claimExtras) external returns (bool); function historicalRewards() external view returns (uint256); function lastTimeRewardApplicable() external view returns (uint256); function lastUpdateTime() external view returns (uint256); function newRewardRatio() external view returns (uint256); function operator() external view returns (address); function periodFinish() external view returns (uint256); function pid() external view returns (uint256); function queueNewRewards(uint256 _rewards) external returns (bool); function queuedRewards() external view returns (uint256); function rewardManager() external view returns (address); function rewardPerToken() external view returns (uint256); function rewardPerTokenStored() external view returns (uint256); function rewardRate() external view returns (uint256); function rewardToken() external view returns (address); function rewards(address) external view returns (uint256); function stake(uint256 _amount) external returns (bool); function stakeAll() external returns (bool); function stakeFor(address _for, uint256 _amount) external returns (bool); function stakingToken() external view returns (address); function totalSupply() external view returns (uint256); function userRewardPerTokenPaid(address) external view returns (uint256); function withdraw(uint256 amount, bool claim) external returns (bool); function withdrawAll(bool claim) external; function withdrawAllAndUnwrap(bool claim) external; function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool); } // File contracts/Staking/Owned.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // https://docs.synthetix.io/contracts/Owned contract Owned { address public owner; address public nominatedOwner; constructor (address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { require(msg.sender == owner, "Only the contract owner may perform this action"); _; } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // File contracts/Uniswap/TransferHelper.sol // Original license: SPDX_License_Identifier: MIT // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } } // File contracts/Utils/ReentrancyGuard.sol // Original license: SPDX_License_Identifier: MIT /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File contracts/Staking/FraxUnifiedFarmTemplate.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ====================== FraxUnifiedFarmTemplate ===================== // ==================================================================== // Farming contract that accounts for veFXS // Overrideable for UniV3, ERC20s, etc // New for V2 // - Multiple reward tokens possible // - Can add to existing locked stakes // - Contract is aware of proxied veFXS // - veFXS multiplier formula changed // Apes together strong // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Jason Huan: https://github.com/jasonhuan // Sam Kazemian: https://github.com/samkazemian // Dennis: github.com/denett // Originally inspired by Synthetix.io, but heavily modified by the Frax team // (Locked, veFXS, and UniV3 portions are new) // https://raw.githubusercontent.com/Synthetixio/synthetix/develop/contracts/StakingRewards.sol // Extra rewards // Balancer // ==================== // import "../Misc_AMOs/balancer/IAuraDeposit.sol"; // import "../Misc_AMOs/balancer/IAuraDepositVault.sol"; // BUNNI // ==================== // import "../Misc_AMOs/bunni/IBunniGauge.sol"; // import "../Misc_AMOs/bunni/IBunniLens.sol"; // import "../Misc_AMOs/bunni/IBunniMinter.sol"; // CONVEX // ==================== contract FraxUnifiedFarmTemplate is Owned, ReentrancyGuard { // -------------------- VARIES -------------------- // Balancer // IAuraDeposit public stakingToken; // IAuraDepositVault public aura_deposit_vault = IAuraDepositVault(0xE557658e3D13d074961265756dC2eFB6c903A763); // Bunni // IBunniGauge public stakingToken; // IBunniLens public lens = IBunniLens(0xb73F303472C4fD4FF3B9f59ce0F9b13E47fbfD19); // IBunniMinter public minter = IBunniMinter(0xF087521Ffca0Fa8A43F5C445773aB37C5f574DA0); /* ========== STATE VARIABLES ========== */ // Instances IveFXS private constant veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0); // Frax related address internal constant frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e; /// @notice fraxPerLPToken is a public view function, although doesn't show the stored value uint256 public fraxPerLPStored; // Constant for various precisions uint256 internal constant MULTIPLIER_PRECISION = 1e18; // Time tracking /// @notice Ending timestamp for the current period uint256 public periodFinish; /// @notice Timestamp of the last update - when this period started uint256 public lastUpdateTime; // Lock time and multiplier settings uint256 public lock_max_multiplier = uint256(2e18); // E18. 1x = e18 uint256 public lock_time_for_max_multiplier = 1 * 1095 * 86400; // 3 years // uint256 public lock_time_for_max_multiplier = 2 * 86400; // 2 days uint256 public lock_time_min = 1; // 1 seconds. If 0, calcCurrLockMultiplier could div by 0 // veFXS related uint256 public vefxs_boost_scale_factor = uint256(4e18); // E18. 4x = 4e18; 100 / scale_factor = % vefxs supply needed for max boost uint256 public vefxs_max_multiplier = uint256(2e18); // E18. 1x = 1e18 uint256 public vefxs_per_frax_for_max_boost = uint256(4e18); // E18. 2e18 means 2 veFXS must be held by the staker per 1 FRAX mapping(address => uint256) internal _vefxsMultiplierStored; mapping(address => bool) internal valid_vefxs_proxies; mapping(address => mapping(address => bool)) internal proxy_allowed_stakers; // Reward addresses, gauge addresses, reward rates, and reward managers /// @notice token addr -> manager addr mapping(address => address) public rewardManagers; address[] internal rewardTokens; address[] internal gaugeControllers; address[] internal rewardDistributors; uint256[] internal rewardRatesManual; mapping(address => bool) internal isRewardToken; /// @notice token addr -> token index mapping(address => uint256) public rewardTokenAddrToIdx; // Reward period uint256 public constant rewardsDuration = 604800; // 7 * 86400 (7 days) // Reward tracking uint256[] private rewardsPerTokenStored; mapping(address => mapping(uint256 => uint256)) private userRewardsPerTokenPaid; // staker addr -> token id -> paid amount mapping(address => mapping(uint256 => uint256)) private rewards; // staker addr -> token id -> reward amount mapping(address => uint256) public lastRewardClaimTime; // staker addr -> timestamp // Gauge tracking uint256[] private last_gauge_relative_weights; uint256[] private last_gauge_time_totals; // Balance tracking uint256 internal _total_liquidity_locked; uint256 internal _total_combined_weight; mapping(address => uint256) internal _locked_liquidity; mapping(address => uint256) internal _combined_weights; /// @notice Keeps track of LP balances proxy-wide. Needed to make sure the proxy boost is kept in line mapping(address => uint256) public proxy_lp_balances; /// @notice Stakers set which proxy(s) they want to use /// @dev Keep public so users can see on the frontend if they have a proxy mapping(address => address) public staker_designated_proxies; // Admin booleans for emergencies and overrides bool public stakesUnlocked; // Release locked stakes in case of emergency bool internal withdrawalsPaused; // For emergencies bool internal rewardsCollectionPaused; // For emergencies bool internal stakingPaused; // For emergencies // For emergencies if a token is overemitted or something else. Only callable once. // Bypasses certain logic, which will cause reward calculations to be off // But the goal is for the users to recover LP, and they couldn't claim the erroneous rewards anyways. // Reward reimbursement claims would be handled with pre-issue earned() snapshots and a claim contract, or similar. bool public withdrawalOnlyShutdown; // Version string public version = "1.0.6"; /* ========== STRUCTS ========== */ // In children... /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require(msg.sender == owner || msg.sender == 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA, "Not owner or timelock"); _; } modifier onlyTknMgrs(address reward_token_address) { require(msg.sender == owner || isTokenManagerFor(msg.sender, reward_token_address), "Not owner or tkn mgr"); _; } modifier updateRewardAndBalanceMdf(address account, bool sync_too) { _updateRewardAndBalance(account, sync_too, false); _; } /* ========== CONSTRUCTOR ========== */ constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRatesManual, address[] memory _gaugeControllers, address[] memory _rewardDistributors ) Owned(_owner) { // Address arrays rewardTokens = _rewardTokens; gaugeControllers = _gaugeControllers; rewardDistributors = _rewardDistributors; rewardRatesManual = _rewardRatesManual; for (uint256 i = 0; i < _rewardTokens.length; i++){ // For fast token address -> token ID lookups later rewardTokenAddrToIdx[_rewardTokens[i]] = i; // Add to the mapping isRewardToken[_rewardTokens[i]] = true; // Initialize the stored rewards rewardsPerTokenStored.push(0); // Initialize the reward managers rewardManagers[_rewardTokens[i]] = _rewardManagers[i]; // Push in empty relative weights to initialize the array last_gauge_relative_weights.push(0); // Push in empty time totals to initialize the array last_gauge_time_totals.push(0); } // Other booleans stakesUnlocked = false; // Initialization lastUpdateTime = block.timestamp; // Sync the first period finish here with the gauge's // periodFinish = IFraxGaugeController(gaugeControllers[0]).time_total(); periodFinish = IFraxGaugeController(0x3669C421b77340B2979d1A00a792CC2ee0FcE737).time_total(); } /* ============= VIEWS ============= */ // ------ REWARD RELATED ------ /// @notice Checks if the caller is a manager for the reward token /// @param caller_addr The address of the caller /// @param reward_token_addr The address of the reward token /// @return bool True if the caller is a manager for the reward token function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool){ if (!isRewardToken[reward_token_addr]) return false; else if (caller_addr == address(0) || reward_token_addr == address(0)) return false; else if (caller_addr == owner) return true; // Contract owner else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager return false; } /// @notice Gets all the reward tokens this contract handles /// @return rewardTokens_ The reward tokens array function getAllRewardTokens() external view returns (address[] memory) { return rewardTokens; } // Last time the reward was applicable function lastTimeRewardApplicable() internal view returns (uint256) { return Math.min(block.timestamp, periodFinish); } /// @notice The amount of reward tokens being paid out per second this period /// @param token_idx The index of the reward token /// @return rwd_rate The reward rate function rewardRates(uint256 token_idx) public view returns (uint256 rwd_rate) { address gauge_controller_address = gaugeControllers[token_idx]; if (gauge_controller_address != address(0)) { rwd_rate = (IFraxGaugeController(gauge_controller_address).global_emission_rate() * last_gauge_relative_weights[token_idx]) / 1e18; } else { rwd_rate = rewardRatesManual[token_idx]; } } // Amount of reward tokens per LP token / liquidity unit function rewardsPerToken() public view returns (uint256[] memory newRewardsPerTokenStored) { if (_total_liquidity_locked == 0 || _total_combined_weight == 0) { return rewardsPerTokenStored; } else { newRewardsPerTokenStored = new uint256[](rewardTokens.length); for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){ newRewardsPerTokenStored[i] = rewardsPerTokenStored[i] + ( ((lastTimeRewardApplicable() - lastUpdateTime) * rewardRates(i) * 1e18) / _total_combined_weight ); } return newRewardsPerTokenStored; } } /// @notice The amount of reward tokens an account has earned / accrued /// @dev In the edge-case of one of the account's stake expiring since the last claim, this will /// @param account The account to check /// @return new_earned Array of reward token amounts earned by the account function earned(address account) public view returns (uint256[] memory new_earned) { uint256[] memory reward_arr = rewardsPerToken(); new_earned = new uint256[](rewardTokens.length); if (_combined_weights[account] > 0){ for (uint256 i = 0; i < rewardTokens.length; i++){ new_earned[i] = ((_combined_weights[account] * (reward_arr[i] - userRewardsPerTokenPaid[account][i])) / 1e18) + rewards[account][i]; } } } /// @notice The total reward tokens emitted in the given period /// @return rewards_per_duration_arr Array of reward token amounts emitted in the current period function getRewardForDuration() external view returns (uint256[] memory rewards_per_duration_arr) { rewards_per_duration_arr = new uint256[](rewardRatesManual.length); for (uint256 i = 0; i < rewardRatesManual.length; i++){ rewards_per_duration_arr[i] = rewardRates(i) * rewardsDuration; } } // ------ LIQUIDITY AND WEIGHTS ------ /// @notice The farm's total locked liquidity / LP tokens /// @return The total locked liquidity function totalLiquidityLocked() external view returns (uint256) { return _total_liquidity_locked; } /// @notice A user's locked liquidity / LP tokens /// @param account The address of the account /// @return The locked liquidity function lockedLiquidityOf(address account) external view returns (uint256) { return _locked_liquidity[account]; } /// @notice The farm's total combined weight of all users /// @return The total combined weight function totalCombinedWeight() external view returns (uint256) { return _total_combined_weight; } /// @notice Total 'balance' used for calculating the percent of the pool the account owns /// @notice Takes into account the locked stake time multiplier and veFXS multiplier /// @param account The address of the account /// @return The combined weight function combinedWeightOf(address account) external view returns (uint256) { return _combined_weights[account]; } /// @notice Calculates the combined weight for an account /// @notice Must be overriden by the child contract /// @dev account The address of the account function calcCurCombinedWeight(address account) public virtual view returns ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) { revert("Need cCCW logic"); } // ------ LOCK RELATED ------ /// @notice Reads the lock boost multiplier for a given duration /// @param secs The duration of the lock in seconds /// @return The multiplier amount function lockMultiplier(uint256 secs) public view returns (uint256) { return Math.min( lock_max_multiplier, (secs * lock_max_multiplier) / lock_time_for_max_multiplier ) ; } // ------ FRAX RELATED ------ /// @notice The amount of FRAX denominated value being boosted that an address has staked /// @param account The address to check /// @return The amount of FRAX value boosted function userStakedFrax(address account) public view returns (uint256) { return (fraxPerLPStored * _locked_liquidity[account]) / MULTIPLIER_PRECISION; } /// @notice The amount of FRAX denominated value being boosted that a proxy address has staked /// @param proxy_address The address to check /// @return The amount of FRAX value boosted function proxyStakedFrax(address proxy_address) public view returns (uint256) { return (fraxPerLPStored * proxy_lp_balances[proxy_address]) / MULTIPLIER_PRECISION; } /// @notice The maximum LP that can get max veFXS boosted for a given address at its current veFXS balance /// @param account The address to check /// @return The maximum LP that can get max veFXS boosted for a given address at its current veFXS balance function maxLPForMaxBoost(address account) external view returns (uint256) { return (veFXS.balanceOf(account) * MULTIPLIER_PRECISION * MULTIPLIER_PRECISION) / (vefxs_per_frax_for_max_boost * fraxPerLPStored); } /// @notice Must be overriden to return the current FRAX per LP token /// @return The current number of FRAX per LP token function fraxPerLPToken() public virtual view returns (uint256) { revert("Need fPLPT logic"); } // ------ veFXS RELATED ------ /// @notice The minimum veFXS required to get max boost for a given address /// @param account The address to check /// @return The minimum veFXS required to get max boost function minVeFXSForMaxBoost(address account) public view returns (uint256) { return (userStakedFrax(account) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } /// @notice The minimum veFXS required to get max boost for a given proxy /// @param proxy_address The proxy address /// @return The minimum veFXS required to get max boost function minVeFXSForMaxBoostProxy(address proxy_address) public view returns (uint256) { return (proxyStakedFrax(proxy_address) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } /// @notice Looks up a staker's proxy /// @param addr The address to check /// @return the_proxy The proxy address, or address(0) function getProxyFor(address addr) public view returns (address){ if (valid_vefxs_proxies[addr]) { // If addr itself is a proxy, return that. // If it farms itself directly, it should use the shared LP tally in proxyStakedFrax return addr; } else { // Otherwise, return the proxy, or address(0) return staker_designated_proxies[addr]; } } /// @notice The multiplier for a given account, based on veFXS /// @param account The account to check /// @return vefxs_multiplier The multiplier boost for the account function veFXSMultiplier(address account) public view returns (uint256 vefxs_multiplier) { // Use either the user's or their proxy's veFXS balance uint256 vefxs_bal_to_use = 0; address the_proxy = getProxyFor(account); vefxs_bal_to_use = (the_proxy == address(0)) ? veFXS.balanceOf(account) : veFXS.balanceOf(the_proxy); // First option based on fraction of total veFXS supply, with an added scale factor uint256 mult_optn_1 = (vefxs_bal_to_use * vefxs_max_multiplier * vefxs_boost_scale_factor) / (veFXS.totalSupply() * MULTIPLIER_PRECISION); // Second based on old method, where the amount of FRAX staked comes into play uint256 mult_optn_2; { uint256 veFXS_needed_for_max_boost; // Need to use proxy-wide FRAX balance if applicable, to prevent exploiting veFXS_needed_for_max_boost = (the_proxy == address(0)) ? minVeFXSForMaxBoost(account) : minVeFXSForMaxBoostProxy(the_proxy); if (veFXS_needed_for_max_boost > 0){ uint256 user_vefxs_fraction = (vefxs_bal_to_use * MULTIPLIER_PRECISION) / veFXS_needed_for_max_boost; mult_optn_2 = (user_vefxs_fraction * vefxs_max_multiplier) / MULTIPLIER_PRECISION; } else mult_optn_2 = 0; // This will happen with the first stake, when user_staked_frax is 0 } // Select the higher of the two vefxs_multiplier = (mult_optn_1 > mult_optn_2 ? mult_optn_1 : mult_optn_2); // Cap the boost to the vefxs_max_multiplier if (vefxs_multiplier > vefxs_max_multiplier) vefxs_multiplier = vefxs_max_multiplier; } /* =============== MUTATIVE FUNCTIONS =============== */ /// @notice Toggle whether a staker can use the proxy's veFXS balance to boost yields /// @notice Proxy must call this first, then the staker must call stakerSetVeFXSProxy function proxyToggleStaker(address staker_address) external { require(valid_vefxs_proxies[msg.sender], "Invalid proxy"); proxy_allowed_stakers[msg.sender][staker_address] = !proxy_allowed_stakers[msg.sender][staker_address]; // Disable the staker's set proxy if it was the toggler and is currently on if (staker_designated_proxies[staker_address] == msg.sender){ staker_designated_proxies[staker_address] = address(0); // Remove the LP as well proxy_lp_balances[msg.sender] -= _locked_liquidity[staker_address]; } } /// @notice After proxy toggles staker to true, staker must call and confirm this /// @param proxy_address The address of the veFXS proxy function stakerSetVeFXSProxy(address proxy_address) external { require(valid_vefxs_proxies[proxy_address], "Invalid proxy"); require(proxy_allowed_stakers[proxy_address][msg.sender], "Proxy has not allowed you yet"); // Corner case sanity check to make sure LP isn't double counted address old_proxy_addr = staker_designated_proxies[msg.sender]; if (old_proxy_addr != address(0)) { // Remove the LP count from the old proxy proxy_lp_balances[old_proxy_addr] -= _locked_liquidity[msg.sender]; } // Set the new proxy staker_designated_proxies[msg.sender] = proxy_address; // Add the the LP as well proxy_lp_balances[proxy_address] += _locked_liquidity[msg.sender]; } // ------ STAKING ------ // In children... // ------ WITHDRAWING ------ // In children... // ------ REWARDS SYNCING ------ function _updateRewardAndBalance(address account, bool sync_too) internal { _updateRewardAndBalance(account, sync_too, false); } function _updateRewardAndBalance(address account, bool sync_too, bool pre_sync_vemxstored) internal { // Skip certain functions if we are in an emergency shutdown if (!withdrawalOnlyShutdown) { // Need to retro-adjust some things if the period hasn't been renewed, then start a new one if (sync_too){ sync(); } } // Used to make sure the veFXS multiplier is correct if a stake is increased, before calcCurCombinedWeight if (pre_sync_vemxstored){ _vefxsMultiplierStored[account] = veFXSMultiplier(account); } if (account != address(0)) { // To keep the math correct, the user's combined weight must be recomputed to account for their // ever-changing veFXS balance. ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) = calcCurCombinedWeight(account); // Calculate the earnings first if (!withdrawalOnlyShutdown) _syncEarned(account); // Update the user's stored veFXS multipliers _vefxsMultiplierStored[account] = new_vefxs_multiplier; // Update the user's and the global combined weights if (new_combined_weight >= old_combined_weight) { uint256 weight_diff = new_combined_weight - old_combined_weight; _total_combined_weight = _total_combined_weight + weight_diff; _combined_weights[account] = old_combined_weight + weight_diff; } else { uint256 weight_diff = old_combined_weight - new_combined_weight; _total_combined_weight = _total_combined_weight - weight_diff; _combined_weights[account] = old_combined_weight - weight_diff; } } } function _syncEarned(address account) internal { if (account != address(0)) { // Calculate the earnings uint256[] memory earned_arr = earned(account); // Update the rewards array for (uint256 i = 0; i < earned_arr.length; i++){ rewards[account][i] = earned_arr[i]; } // Update the rewards paid array for (uint256 i = 0; i < earned_arr.length; i++){ userRewardsPerTokenPaid[account][i] = rewardsPerTokenStored[i]; } } } // ------ REWARDS CLAIMING ------ /// @notice A function that can be overridden to add extra logic to the getReward function /// @param destination_address The address to send the rewards to function getRewardExtraLogic(address destination_address) public nonReentrant { require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); require(rewardsCollectionPaused == false, "Rewards collection paused"); return _getRewardExtraLogic(msg.sender, destination_address); } function _getRewardExtraLogic(address rewardee, address destination_address) internal virtual { revert("Need gREL logic"); } // Two different getReward functions are needed because of delegateCall and msg.sender issues // For backwards-compatibility /// @notice Claims rewards to destination address /// @param destination_address The address to send the rewards to /// @return rewards_before The rewards available before the claim function getReward(address destination_address) external nonReentrant returns (uint256[] memory) { return _getReward(msg.sender, destination_address, true); } /// @notice Claims rewards to destination address & wether to do extra logic /// @param destination_address The address to send the rewards to /// @param claim_extra_too Whether to do extra logic /// @return rewards_before The rewards available before the claim function getReward2(address destination_address, bool claim_extra_too) external nonReentrant returns (uint256[] memory) { return _getReward(msg.sender, destination_address, claim_extra_too); } // No withdrawer == msg.sender check needed since this is only internally callable function _getReward(address rewardee, address destination_address, bool do_extra_logic) internal updateRewardAndBalanceMdf(rewardee, true) returns (uint256[] memory rewards_before) { // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Make sure rewards collection isn't paused require(rewardsCollectionPaused == false, "Rewards collection paused"); // Update the last reward claim time first, as an extra reentrancy safeguard lastRewardClaimTime[rewardee] = block.timestamp; // Update the rewards array and distribute rewards rewards_before = new uint256[](rewardTokens.length); for (uint256 i = 0; i < rewardTokens.length; i++){ rewards_before[i] = rewards[rewardee][i]; rewards[rewardee][i] = 0; if (rewards_before[i] > 0) { TransferHelper.safeTransfer(rewardTokens[i], destination_address, rewards_before[i]); emit RewardPaid(rewardee, rewards_before[i], rewardTokens[i], destination_address); } } // Handle additional reward logic if (do_extra_logic) { _getRewardExtraLogic(rewardee, destination_address); } } // ------ FARM SYNCING ------ // If the period expired, renew it function retroCatchUp() internal { // Catch up the old rewards first _updateStoredRewardsAndTime(); // Pull in rewards from the rewards distributor, if applicable for (uint256 i = 0; i < rewardDistributors.length; i++){ address reward_distributor_address = rewardDistributors[i]; if (reward_distributor_address != address(0)) { IFraxGaugeFXSRewardsDistributor(reward_distributor_address).distributeReward(address(this)); } } // Ensure the provided reward amount is not more than the balance in the contract. // This keeps the reward rate in the right range, preventing overflows due to // very high values of rewardRate in the earned and rewardsPerToken functions; // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow. uint256 num_periods_elapsed = uint256(block.timestamp - periodFinish) / rewardsDuration; // Floor division to the nearest period // Make sure there are enough tokens to renew the reward period for (uint256 i = 0; i < rewardTokens.length; i++){ require((rewardRates(i) * rewardsDuration * (num_periods_elapsed + 1)) <= IERC20(rewardTokens[i]).balanceOf(address(this)), string(abi.encodePacked("Not enough reward tokens available: ", rewardTokens[i])) ); } // uint256 old_lastUpdateTime = lastUpdateTime; // uint256 new_lastUpdateTime = block.timestamp; // lastUpdateTime = periodFinish; periodFinish = periodFinish + ((num_periods_elapsed + 1) * rewardsDuration); // Aura & Balancer Gauge Rewards // ========================================== // Pull in rewards and set the reward rate for one week, based off of that // If the rewards get messed up for some reason, set this to 0 and it will skip // Should only be called once per week max // if (rewardRatesManual[1] != 0) { // // AURA & BAL // // ==================================== // uint256 aura_before = IERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 bal_before = IERC20(rewardTokens[2]).balanceOf(address(this)); // aura_deposit_vault.getReward(address(this), true); // uint256 aura_after = IERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 bal_after = IERC20(rewardTokens[2]).balanceOf(address(this)); // // Set the new reward rates // rewardRatesManual[1] = (aura_after - aura_before) / rewardsDuration; // AURA // rewardRatesManual[2] = (bal_after - bal_before) / rewardsDuration; // BAL // } // Bunni oLIT rewards // ========================================== // Pull in rewards and set the reward rate for one week, based off of that // If the rewards get messed up for some reason, set this to 0 and it will skip // Should only be called once per week max // if (rewardRatesManual[1] != 0) { // // oLIT // // ==================================== // uint256 olit_before = IERC20(rewardTokens[1]).balanceOf(address(this)); // minter.mint(address(stakingToken)); // uint256 olit_after = IERC20(rewardTokens[1]).balanceOf(address(this)); // // Set the new reward rate // rewardRatesManual[1] = (olit_after - olit_before) / rewardsDuration; // } // CONVEX EXTRA REWARDS (OLD METHOD) // ========================================== // Pull in rewards and set the reward rate for one week, based off of that // If the rewards get messed up for some reason, set this to 0 and it will skip // if (rewardRatesManual[1] != 0 && rewardRatesManual[2] != 0) { // // CRV & CVX // // ==================================== // uint256 crv_before = ERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 cvx_before = ERC20(rewardTokens[2]).balanceOf(address(this)); // IConvexBaseRewardPool(0x329cb014b562d5d42927cfF0dEdF4c13ab0442EF).getReward( // address(this), // true // ); // uint256 crv_after = ERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 cvx_after = ERC20(rewardTokens[2]).balanceOf(address(this)); // // Set the new reward rate // rewardRatesManual[1] = (crv_after - crv_before) / rewardsDuration; // rewardRatesManual[2] = (cvx_after - cvx_before) / rewardsDuration; // } // Make sure everything is caught up again _updateStoredRewardsAndTime(); } function _updateStoredRewardsAndTime() internal { // Get the rewards uint256[] memory rewards_per_token = rewardsPerToken(); // Update the rewardsPerTokenStored for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){ rewardsPerTokenStored[i] = rewards_per_token[i]; } // Update the last stored time lastUpdateTime = lastTimeRewardApplicable(); } /// @notice Updates the gauge weights, if applicable /// @param force_update If true, will update the weights even if the time hasn't elapsed function sync_gauge_weights(bool force_update) public { // Loop through the gauge controllers for (uint256 i = 0; i < gaugeControllers.length; i++){ address gauge_controller_address = gaugeControllers[i]; if (gauge_controller_address != address(0)) { if (force_update || (block.timestamp > last_gauge_time_totals[i])){ // Update the gauge_relative_weight last_gauge_relative_weights[i] = IFraxGaugeController(gauge_controller_address).gauge_relative_weight_write(address(this), block.timestamp); last_gauge_time_totals[i] = IFraxGaugeController(gauge_controller_address).time_total(); } } } } /// @notice Updates gauge weights, fraxPerLP, pulls in new rewards or updates rewards function sync() public { // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Sync the gauge weight, if applicable sync_gauge_weights(false); // Update the fraxPerLPStored fraxPerLPStored = fraxPerLPToken(); if (block.timestamp >= periodFinish) { retroCatchUp(); } else { _updateStoredRewardsAndTime(); } } /* ========== RESTRICTED FUNCTIONS - Curator callable ========== */ // ------ FARM SYNCING ------ // In children... // ------ PAUSES ------ /// @notice Owner or governance can pause/unpause staking, withdrawals, rewards collection, and collectRewardsOnWithdrawal /// @param _stakingPaused Whether staking is paused /// @param _withdrawalsPaused Whether withdrawals are paused /// @param _rewardsCollectionPaused Whether rewards collection is paused /// @param _withdrawalOnlyShutdown Whether you can only withdraw. Only settable once function setPauses( bool _stakingPaused, bool _withdrawalsPaused, bool _rewardsCollectionPaused, bool _withdrawalOnlyShutdown ) external onlyByOwnGov { stakingPaused = _stakingPaused; withdrawalsPaused = _withdrawalsPaused; rewardsCollectionPaused = _rewardsCollectionPaused; // Only settable once. Rewards math will be permanently wrong afterwards, so only use // for recovering LP if(_withdrawalOnlyShutdown && !withdrawalOnlyShutdown) withdrawalOnlyShutdown = true; } /* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */ /// @notice Owner or governance can unlock stakes - irreversible! function unlockStakes() external onlyByOwnGov { stakesUnlocked = !stakesUnlocked; } /// @notice Owner or governance sets whether an address is a valid veFXS proxy /// @param _proxy_addr The address to set function toggleValidVeFXSProxy(address _proxy_addr) external onlyByOwnGov { valid_vefxs_proxies[_proxy_addr] = !valid_vefxs_proxies[_proxy_addr]; } /// @notice Allows owner to recover any ERC20 or token manager to recover their reward token. /// @param tokenAddress The address of the token to recover /// @param tokenAmount The amount of the token to recover function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) { // Check if the desired token is a reward token bool isRewTkn = isRewardToken[tokenAddress]; // Only the reward managers can take back their reward tokens // Also, other tokens, like the staking token, airdrops, or accidental deposits, can be withdrawn by the owner if ( (isRewTkn && rewardManagers[tokenAddress] == msg.sender) || (!isRewTkn && (msg.sender == owner)) ) { // // Aura & Balancer // // Withdraw the tokens from the Aura vault. Do not claim // // ========================================= // if (tokenAddress == address(stakingToken)) aura_deposit_vault.withdraw(tokenAmount, false); TransferHelper.safeTransfer(tokenAddress, msg.sender, tokenAmount); return; } // If none of the above conditions are true else { revert("No valid tokens to recover"); } } /// @notice Sets multiple variables at once /// @param _misc_vars The variables to set: /// [0]: uint256 _lock_max_multiplier, /// [1] uint256 _vefxs_max_multiplier, /// [2] uint256 _vefxs_per_frax_for_max_boost, /// [3] uint256 _vefxs_boost_scale_factor, /// [4] uint256 _lock_time_for_max_multiplier, /// [5] uint256 _lock_time_min /// [6] uint256 _max_stake_limit (must be at greater or equal to old value) function setMiscVariables( uint256[6] memory _misc_vars // [0]: uint256 _lock_max_multiplier, // [1] uint256 _vefxs_max_multiplier, // [2] uint256 _vefxs_per_frax_for_max_boost, // [3] uint256 _vefxs_boost_scale_factor, // [4] uint256 _lock_time_for_max_multiplier, // [5] uint256 _lock_time_min ) external onlyByOwnGov { require(_misc_vars[0] >= MULTIPLIER_PRECISION, "Must be >= MUL PREC"); require((_misc_vars[1] >= 0) && (_misc_vars[2] >= 0) && (_misc_vars[3] >= 0), "Must be >= 0"); require((_misc_vars[4] >= 1) && (_misc_vars[5] >= 1), "Must be >= 1"); lock_max_multiplier = _misc_vars[0]; vefxs_max_multiplier = _misc_vars[1]; vefxs_per_frax_for_max_boost = _misc_vars[2]; vefxs_boost_scale_factor = _misc_vars[3]; lock_time_for_max_multiplier = _misc_vars[4]; lock_time_min = _misc_vars[5]; } // The owner or the reward token managers can set reward rates /// @notice Allows owner or reward token managers to set the reward rate for a given reward token /// @param reward_token_address The address of the reward token /// @param _new_rate The new reward rate (token amount divided by reward period duration) /// @param _gauge_controller_address The address of the gauge controller for this reward token /// @param _rewards_distributor_address The address of the rewards distributor for this reward token function setRewardVars(address reward_token_address, uint256 _new_rate, address _gauge_controller_address, address _rewards_distributor_address) external onlyTknMgrs(reward_token_address) { rewardRatesManual[rewardTokenAddrToIdx[reward_token_address]] = _new_rate; gaugeControllers[rewardTokenAddrToIdx[reward_token_address]] = _gauge_controller_address; rewardDistributors[rewardTokenAddrToIdx[reward_token_address]] = _rewards_distributor_address; } // The owner or the reward token managers can change managers /// @notice Allows owner or reward token managers to change the reward manager for a given reward token /// @param reward_token_address The address of the reward token /// @param new_manager_address The new reward manager address function changeTokenManager(address reward_token_address, address new_manager_address) external onlyTknMgrs(reward_token_address) { rewardManagers[reward_token_address] = new_manager_address; } /* ========== EVENTS ========== */ event RewardPaid(address indexed user, uint256 amount, address token_address, address destination_address); /* ========== A CHICKEN ========== */ // // ,~. // ,-'__ `-, // {,-' `. } ,') // ,( a ) `-.__ ,',')~, // <=.) ( `-.__,==' ' ' '} // ( ) /) // `-'\ , ) // | \ `~. / // \ `._ \ / // \ `._____,' ,' // `-. ,' // `-._ _,-' // 77jj' // //_|| // __//--'/` // ,--'/` ' // // [hjw] https://textart.io/art/vw6Sa3iwqIRGkZsN1BC2vweF/chicken } // File contracts/Staking/FraxUnifiedFarm_ERC20.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================= FraxUnifiedFarm_ERC20 ====================== // ==================================================================== // For ERC20 Tokens // Uses FraxUnifiedFarmTemplate.sol // -------------------- VARIES -------------------- // Balancer // import "../Misc_AMOs/balancer/IBalancerGauge.sol"; // Bunni // import "../Misc_AMOs/bunni/IBunniGauge.sol"; // Convex wrappers // import "../Curve/ICurvefrxETHETHPool.sol"; // import "../Misc_AMOs/convex/IConvexStakingWrapperFrax.sol"; // import "../Misc_AMOs/convex/IDepositToken.sol"; // import "../Misc_AMOs/curve/I2pool.sol"; // import "../Misc_AMOs/curve/I2poolToken.sol"; // import "../Misc_AMOs/curve/I2poolTokenNoLending.sol"; // import "../Misc_AMOs/curve/ICurveStableSwapNG.sol"; // import "../Misc_AMOs/curve/ICurveStableSwapMetaNG.sol"; // import "../Misc_AMOs/curve/ICurveTricryptoOptimizedWETH.sol"; // Convex FXB // import "../Misc_AMOs/curve/ICurveStableSwapNG.sol"; // import '../FXB/IFXB.sol'; // Fraxlend // import '../Fraxlend/IFraxlendPair.sol'; // Fraxswap // import '../Fraxswap/core/interfaces/IFraxswapPair.sol'; // G-UNI // import "../Misc_AMOs/gelato/IGUniPool.sol"; // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // import "../Misc_AMOs/kyberswap/elastic/IKyberSwapFarmingToken.sol"; // Morpho // mStable // import '../Misc_AMOs/mstable/IFeederPool.sol'; // StakeDAO sdETH-FraxPut // import '../Misc_AMOs/stakedao/IOpynPerpVault.sol'; // StakeDAO Vault // import '../Misc_AMOs/stakedao/IStakeDaoVault.sol'; // Uniswap V2 // import '../Uniswap/Interfaces/IUniswapV2Pair.sol'; // Vesper // import '../Misc_AMOs/vesper/IVPool.sol'; // ------------------------------------------------ contract FraxUnifiedFarm_ERC20 is FraxUnifiedFarmTemplate { /* ========== STATE VARIABLES ========== */ // -------------------- COMMON -------------------- bool internal frax_is_token0; // -------------------- VARIES -------------------- // Bunni // Declared in FraxUnifiedFarmTemplate.sol // Balancer // Declared in FraxUnifiedFarmTemplate.sol // Convex crvUSD/FRAX // IConvexStakingWrapperFrax public stakingToken; // I2poolTokenNoLending public curveToken; // ICurvefrxETHETHPool public curvePool; // Convex stkcvxFPIFRAX, stkcvxFRAXBP, etc // IConvexStakingWrapperFrax public stakingToken; // I2poolToken public curveToken; // ICurveStableSwapNG public curveToken; // ICurveStableSwapMetaNG public curveToken; // ICurveTricryptoOptimizedWETH public curveToken; // I2pool public curvePool; // ICurvefrxETHETHPool public curvePool; // ICurveStableSwapNG public curvePool; // ICurveStableSwapMetaNG public curvePool; // ICurveTricryptoOptimizedWETH public curvePool; // Fraxswap // IFraxswapPair public stakingToken; // Fraxlend // IFraxlendPair public stakingToken; // G-UNI // IGUniPool public stakingToken; // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // IKyberSwapFarmingToken public stakingToken; // Morpho IMetaMorpho public stakingToken; // mStable // IFeederPool public stakingToken; // sdETH-FraxPut Vault // IOpynPerpVault public stakingToken; // StakeDAO Vault // IStakeDaoVault public stakingToken; // Uniswap V2 // IUniswapV2Pair public stakingToken; // Vesper // IVPool public stakingToken; // ------------------------------------------------ // Stake tracking mapping(address => LockedStake[]) public lockedStakes; /* ========== STRUCTS ========== */ // Struct for the stake struct LockedStake { bytes32 kek_id; uint256 start_timestamp; uint256 liquidity; uint256 ending_timestamp; uint256 lock_multiplier; // 6 decimals of precision. 1x = 1000000 } /* ========== CONSTRUCTOR ========== */ constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRatesManual, address[] memory _gaugeControllers, address[] memory _rewardDistributors, address _stakingToken ) FraxUnifiedFarmTemplate(_owner, _rewardTokens, _rewardManagers, _rewardRatesManual, _gaugeControllers, _rewardDistributors) { // -------------------- VARIES (USE CHILD FOR LOGIC) -------------------- // Bunni // USE CHILD // Convex stkcvxFPIFRAX, stkcvxFRAXBP, etc // USE CHILD // Fraxlend // USE CHILD // Fraxswap // USE CHILD // G-UNI // stakingToken = IGUniPool(_stakingToken); // address token0 = address(stakingToken.token0()); // frax_is_token0 = (token0 == frax_address); // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // stakingToken = IKyberSwapFarmingToken(_stakingToken); // Morpho // USE CHILD // mStable // stakingToken = IFeederPool(_stakingToken); // StakeDAO sdETH-FraxPut Vault // stakingToken = IOpynPerpVault(_stakingToken); // StakeDAO Vault // stakingToken = IStakeDaoVault(_stakingToken); // Uniswap V2 // stakingToken = IUniswapV2Pair(_stakingToken); // address token0 = stakingToken.token0(); // if (token0 == frax_address) frax_is_token0 = true; // else frax_is_token0 = false; // Vesper // stakingToken = IVPool(_stakingToken); } /* ============= VIEWS ============= */ // ------ FRAX RELATED ------ function fraxPerLPToken() public virtual view override returns (uint256) { // Get the amount of FRAX 'inside' of the lp tokens uint256 frax_per_lp_token; // Balancer // ============================================ // USE CHILD // Bunni // ============================================ // USE CHILD // Convex stkcvxFPIFRAX and stkcvxFRAXBP only // ============================================ // USE CHILD // Convex Stable/FRAXBP // ============================================ // USE CHILD // Convex Volatile/FRAXBP // ============================================ // USE CHILD // Fraxlend // ============================================ // USE CHILD // Fraxswap // ============================================ // USE CHILD // G-UNI // ============================================ // { // (uint256 reserve0, uint256 reserve1) = stakingToken.getUnderlyingBalances(); // uint256 total_frax_reserves = frax_is_token0 ? reserve0 : reserve1; // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // KyberSwap Elastic KyberSwapFarmingToken (KS-FT) // ============================================ // USE CHILD // Morpho // ============================================ // USE CHILD // mStable // ============================================ // { // uint256 total_frax_reserves; // (, IFeederPool.BassetData memory vaultData) = (stakingToken.getBasset(frax_address)); // total_frax_reserves = uint256(vaultData.vaultBalance); // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // StakeDAO sdETH-FraxPut Vault // ============================================ // { // uint256 frax3crv_held = stakingToken.totalUnderlyingControlled(); // // Optimistically assume 50/50 FRAX/3CRV ratio in the metapool to save gas // frax_per_lp_token = ((frax3crv_held * 1e18) / stakingToken.totalSupply()) / 2; // } // StakeDAO Vault // ============================================ // { // uint256 frax3crv_held = stakingToken.balance(); // // Optimistically assume 50/50 FRAX/3CRV ratio in the metapool to save gas // frax_per_lp_token = ((frax3crv_held * 1e18) / stakingToken.totalSupply()) / 2; // } // Uniswap V2 // ============================================ // { // uint256 total_frax_reserves; // (uint256 reserve0, uint256 reserve1, ) = (stakingToken.getReserves()); // if (frax_is_token0) total_frax_reserves = reserve0; // else total_frax_reserves = reserve1; // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // Vesper // ============================================ // frax_per_lp_token = stakingToken.pricePerShare(); return frax_per_lp_token; } // ------ LIQUIDITY AND WEIGHTS ------ function calcCurrLockMultiplier(address account, uint256 stake_idx) public view returns (uint256 midpoint_lock_multiplier) { // Get the stake LockedStake memory thisStake = lockedStakes[account][stake_idx]; // Handles corner case where user never claims for a new stake // Don't want the multiplier going above the max uint256 accrue_start_time; if (lastRewardClaimTime[account] < thisStake.start_timestamp) { accrue_start_time = thisStake.start_timestamp; } else { accrue_start_time = lastRewardClaimTime[account]; } // If the lock is expired if (thisStake.ending_timestamp <= block.timestamp) { // If the lock expired in the time since the last claim, the weight needs to be proportionately averaged this time if (lastRewardClaimTime[account] < thisStake.ending_timestamp){ uint256 time_before_expiry = thisStake.ending_timestamp - accrue_start_time; uint256 time_after_expiry = block.timestamp - thisStake.ending_timestamp; // Average the pre-expiry lock multiplier uint256 pre_expiry_avg_multiplier = lockMultiplier(time_before_expiry / 2); // Get the weighted-average lock_multiplier // uint256 numerator = (pre_expiry_avg_multiplier * time_before_expiry) + (MULTIPLIER_PRECISION * time_after_expiry); uint256 numerator = (pre_expiry_avg_multiplier * time_before_expiry) + (0 * time_after_expiry); midpoint_lock_multiplier = numerator / (time_before_expiry + time_after_expiry); } else { // Otherwise, it needs to just be 1x // midpoint_lock_multiplier = MULTIPLIER_PRECISION; // Otherwise, it needs to just be 0x midpoint_lock_multiplier = 0; } } // If the lock is not expired else { // Decay the lock multiplier based on the time left uint256 avg_time_left; { uint256 time_left_p1 = thisStake.ending_timestamp - accrue_start_time; uint256 time_left_p2 = thisStake.ending_timestamp - block.timestamp; avg_time_left = (time_left_p1 + time_left_p2) / 2; } midpoint_lock_multiplier = lockMultiplier(avg_time_left); } // Sanity check: make sure it never goes above the initial multiplier if (midpoint_lock_multiplier > thisStake.lock_multiplier) midpoint_lock_multiplier = thisStake.lock_multiplier; } // Calculate the combined weight for an account function calcCurCombinedWeight(address account) public override view returns ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) { // Get the old combined weight old_combined_weight = _combined_weights[account]; // Get the veFXS multipliers // For the calculations, use the midpoint (analogous to midpoint Riemann sum) new_vefxs_multiplier = veFXSMultiplier(account); uint256 midpoint_vefxs_multiplier; if ( (_locked_liquidity[account] == 0 && _combined_weights[account] == 0) || (new_vefxs_multiplier >= _vefxsMultiplierStored[account]) ) { // This is only called for the first stake to make sure the veFXS multiplier is not cut in half // Also used if the user increased or maintained their position midpoint_vefxs_multiplier = new_vefxs_multiplier; } else { // Handles natural decay with a non-increased veFXS position midpoint_vefxs_multiplier = (new_vefxs_multiplier + _vefxsMultiplierStored[account]) / 2; } // Loop through the locked stakes, first by getting the liquidity * lock_multiplier portion new_combined_weight = 0; for (uint256 i = 0; i < lockedStakes[account].length; i++) { LockedStake memory thisStake = lockedStakes[account][i]; // Calculate the midpoint lock multiplier uint256 midpoint_lock_multiplier = calcCurrLockMultiplier(account, i); // Calculate the combined boost uint256 liquidity = thisStake.liquidity; uint256 combined_boosted_amount = liquidity + ((liquidity * (midpoint_lock_multiplier + midpoint_vefxs_multiplier)) / MULTIPLIER_PRECISION); new_combined_weight += combined_boosted_amount; } } // ------ LOCK RELATED ------ // All the locked stakes for a given account function lockedStakesOf(address account) external view returns (LockedStake[] memory) { return lockedStakes[account]; } // Returns the length of the locked stakes for a given account function lockedStakesOfLength(address account) external view returns (uint256) { return lockedStakes[account].length; } // // All the locked stakes for a given account [old-school method] // function lockedStakesOfMultiArr(address account) external view returns ( // bytes32[] memory kek_ids, // uint256[] memory start_timestamps, // uint256[] memory liquidities, // uint256[] memory ending_timestamps, // uint256[] memory lock_multipliers // ) { // for (uint256 i = 0; i < lockedStakes[account].length; i++){ // LockedStake memory thisStake = lockedStakes[account][i]; // kek_ids[i] = thisStake.kek_id; // start_timestamps[i] = thisStake.start_timestamp; // liquidities[i] = thisStake.liquidity; // ending_timestamps[i] = thisStake.ending_timestamp; // lock_multipliers[i] = thisStake.lock_multiplier; // } // } /* =============== MUTATIVE FUNCTIONS =============== */ // ------ STAKING ------ function _updateLiqAmts(address staker_address, uint256 amt, bool is_add) internal { // Get the proxy address address the_proxy = getProxyFor(staker_address); if (is_add) { // Update total liquidities _total_liquidity_locked += amt; _locked_liquidity[staker_address] += amt; // Update the proxy if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += amt; } else { // Update total liquidities _total_liquidity_locked -= amt; _locked_liquidity[staker_address] -= amt; // Update the proxy if (the_proxy != address(0)) proxy_lp_balances[the_proxy] -= amt; } // Need to call to update the combined weights _updateRewardAndBalance(staker_address, false, true); } function _getStake(address staker_address, bytes32 kek_id) internal view returns (LockedStake memory locked_stake, uint256 arr_idx) { if (kek_id != 0) { for (uint256 i = 0; i < lockedStakes[staker_address].length; i++){ if (kek_id == lockedStakes[staker_address][i].kek_id){ locked_stake = lockedStakes[staker_address][i]; arr_idx = i; break; } } } require(kek_id != 0 && locked_stake.kek_id == kek_id, "Stake not found"); } // Add additional LPs to an existing locked stake function lockAdditional(bytes32 kek_id, uint256 addl_liq) nonReentrant public { // Make sure staking isn't paused require(!stakingPaused, "Staking paused"); // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Claim rewards at the old balance first _getReward(msg.sender, msg.sender, true); // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id); // Calculate the new amount uint256 new_amt = thisStake.liquidity + addl_liq; // Checks require(addl_liq >= 0, "Must be positive"); // Pull the tokens from the sender TransferHelper.safeTransferFrom(address(stakingToken), msg.sender, address(this), addl_liq); // // Aura & Balancer // // Deposit the tokens into the Aura vault // // ========================================= // stakingToken.approve(address(aura_deposit_vault), addl_liq); // aura_deposit_vault.stake(addl_liq); // Update the stake lockedStakes[msg.sender][theArrayIndex] = LockedStake( kek_id, thisStake.start_timestamp, new_amt, thisStake.ending_timestamp, thisStake.lock_multiplier ); // Update liquidities _updateLiqAmts(msg.sender, addl_liq, true); emit LockedAdditional(msg.sender, kek_id, addl_liq); } // Extends the lock of an existing stake function lockLonger(bytes32 kek_id, uint256 new_ending_ts) nonReentrant public { // Make sure staking isn't paused require(!stakingPaused, "Staking paused"); // Make sure you are not in shutdown require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); // Claim rewards at the old balance first _getReward(msg.sender, msg.sender, true); // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id); // Check require(new_ending_ts > block.timestamp, "Must be in the future"); // Calculate some times uint256 time_left = (thisStake.ending_timestamp > block.timestamp) ? thisStake.ending_timestamp - block.timestamp : 0; uint256 new_secs = new_ending_ts - block.timestamp; // Checks // require(time_left > 0, "Already expired"); require(new_secs > time_left, "Cannot shorten lock time"); require(new_secs >= lock_time_min, "Minimum stake time not met"); require(new_secs <= lock_time_for_max_multiplier, "Trying to lock for too long"); // Update the stake lockedStakes[msg.sender][theArrayIndex] = LockedStake( kek_id, block.timestamp, thisStake.liquidity, new_ending_ts, lockMultiplier(new_secs) ); // Need to call to update the combined weights _updateRewardAndBalance(msg.sender, false, true); emit LockedLonger(msg.sender, kek_id, new_secs, block.timestamp, new_ending_ts); } // Two different stake functions are needed because of delegateCall and msg.sender issues (important for proxies) function stakeLocked(uint256 liquidity, uint256 secs) nonReentrant external returns (bytes32) { return _stakeLocked(msg.sender, msg.sender, liquidity, secs, block.timestamp); } // If this were not internal, and source_address had an infinite approve, this could be exploitable // (pull funds from source_address and stake for an arbitrary staker_address) function _stakeLocked( address staker_address, address source_address, uint256 liquidity, uint256 secs, uint256 start_timestamp ) internal updateRewardAndBalanceMdf(staker_address, true) returns (bytes32) { require(!withdrawalOnlyShutdown, "Only withdrawals allowed"); require(!stakingPaused, "Staking paused"); require(secs >= lock_time_min, "Minimum stake time not met"); require(secs <= lock_time_for_max_multiplier,"Trying to lock for too long"); // Pull in the required token(s) // Varies per farm TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity); // // Aura & Balancer // // Deposit the tokens into the Aura vault // // ========================================= // stakingToken.approve(address(aura_deposit_vault), liquidity); // aura_deposit_vault.stake(liquidity); // Get the lock multiplier and kek_id uint256 lock_multiplier = lockMultiplier(secs); bytes32 kek_id = keccak256(abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address])); // Create the locked stake lockedStakes[staker_address].push(LockedStake( kek_id, start_timestamp, liquidity, start_timestamp + secs, lock_multiplier )); // Update liquidities _updateLiqAmts(staker_address, liquidity, true); emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address); return kek_id; } // ------ WITHDRAWING ------ /// @notice Withdraw a stake. /// @param kek_id The id for the stake /// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless) /// @dev Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues (important for migration) function withdrawLocked(bytes32 kek_id, address destination_address, bool claim_rewards_deprecated) nonReentrant external returns (uint256) { require(withdrawalsPaused == false, "Withdrawals paused"); return _withdrawLocked(msg.sender, destination_address, kek_id, claim_rewards_deprecated); } /// @notice No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper functions like withdraw(), migrator_withdraw_unlocked() and migrator_withdraw_locked() /// @param staker_address The address of the staker /// @param destination_address Destination address for the withdrawn LP /// @param kek_id The id for the stake /// @param claim_rewards_deprecated DEPRECATED, has no effect (always claims rewards regardless) function _withdrawLocked( address staker_address, address destination_address, bytes32 kek_id, bool claim_rewards_deprecated ) internal returns (uint256) { // Collect rewards first and then update the balances // withdrawalOnlyShutdown to be used in an emergency situation if reward is overemitted or not available // and the user can forfeit rewards to get their principal back. if (withdrawalOnlyShutdown) { // Do nothing. } else { // Get the reward _getReward(staker_address, destination_address, true); } // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(staker_address, kek_id); require(block.timestamp >= thisStake.ending_timestamp || stakesUnlocked == true, "Stake is still locked!"); uint256 liquidity = thisStake.liquidity; if (liquidity > 0) { // // Aura & Balancer // // Withdraw the tokens from the Aura vault. Do not claim // // ========================================= // aura_deposit_vault.withdraw(liquidity, false); // Give the tokens to the destination_address // Should throw if insufficient balance TransferHelper.safeTransfer(address(stakingToken), destination_address, liquidity); // Remove the stake from the array delete lockedStakes[staker_address][theArrayIndex]; // Update liquidities _updateLiqAmts(staker_address, liquidity, false); emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address); } return liquidity; } function _getRewardExtraLogic(address rewardee, address destination_address) internal override { // Do nothing } /* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */ // Inherited... /* ========== EVENTS ========== */ event LockedAdditional(address indexed user, bytes32 kek_id, uint256 amount); event LockedLonger(address indexed user, bytes32 kek_id, uint256 new_secs, uint256 new_start_ts, uint256 new_end_ts); event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address); event WithdrawLocked(address indexed user, uint256 liquidity, bytes32 kek_id, address destination_address); } // File contracts/Oracle/AggregatorV3Interface.sol // Original license: SPDX_License_Identifier: MIT interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/Staking/Variants/FraxUnifiedFarm_ERC20_Other.sol // Original license: SPDX_License_Identifier: GPL-2.0-or-later // Balancer // ========================= // import "../../Misc_AMOs/balancer/IAuraDeposit.sol"; // import "../../Misc_AMOs/balancer/IAuraDepositVault.sol"; // import "../../Misc_AMOs/balancer/IBalancerVault.sol"; // import "../../Misc_AMOs/balancer/IComposableStablePool.sol"; // Bunni // ========================= // import "../../Misc_AMOs/bunni/IBunniTokenLP.sol"; // import "../../Misc_AMOs/bunni/IBunniGauge.sol"; // import "../../Misc_AMOs/bunni/IBunniLens.sol"; // import "../../Misc_AMOs/bunni/IBunniMinter.sol"; // import "../../Uniswap_V3/IUniswapV3Pool.sol"; // Morpho // ========================= contract FraxUnifiedFarm_ERC20_Other is FraxUnifiedFarm_ERC20 { // frxETH Pricing // AggregatorV3Interface internal priceFeedETHUSD = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); // Aura / Balancer // IComposableStablePool public bal_vanilla_lp_tkn; // IBalancerVault public bal_vanilla_vault; // Bunni // IBunniTokenLP public lp_tkn; // IUniswapV3Pool public univ3_pool; // Morpho string public farm_type = "ERC20_Convex_Other"; constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRates, address[] memory _gaugeControllers, address[] memory _rewardDistributors, address _stakingToken ) FraxUnifiedFarm_ERC20(_owner , _rewardTokens, _rewardManagers, _rewardRates, _gaugeControllers, _rewardDistributors, _stakingToken) { // COMMENTED OUT SO COMPILER DOESNT COMPLAIN. UNCOMMENT WHEN DEPLOYING // Balancer // stakingToken = IAuraDeposit(_stakingToken); // bal_vanilla_lp_tkn = IComposableStablePool(0xB06bFBD7b50F80c8d9dA57Fc4cF5CBD5B3E2f148); // bal_vanilla_vault = IBalancerVault(bal_vanilla_lp_tkn.getVault()); // Bunni // stakingToken = IBunniGauge(_stakingToken); // lp_tkn = IBunniTokenLP(stakingToken.lp_token()); // univ3_pool = IUniswapV3Pool(lp_tkn.pool()); // address token0 = univ3_pool.token0(); // frax_is_token0 = (token0 == frax_address); // Morpho stakingToken = IMetaMorpho(_stakingToken); } // Aura & Balancer // ---------------------------------------- // Nothing // Bunni // ---------------------------------------- // function setBunniAddrs(address _lens, address _minter) public onlyByOwnGov { // lens = IBunniLens(_lens); // minter = IBunniMinter(_minter); // } // // In case the rewards get screwed up // function toggleBunni3rdPartyOLITClaimer(address _claimer) public onlyByOwnGov { // minter.toggle_approve_mint(_claimer); // } // Morpho // ---------------------------------------- // Nothing // // frxETH pricing // // ---------------------------------------- // function getLatestETHPriceE8() public view returns (int) { // // Returns in E8 // (uint80 roundID, int price, , uint256 updatedAt, uint80 answeredInRound) = priceFeedETHUSD.latestRoundData(); // require(price >= 0 && updatedAt!= 0 && answeredInRound >= roundID, "Invalid chainlink price"); // return price; // } // function setETHUSDOracle(address _eth_usd_oracle_address) public onlyByOwnGov { // require(_eth_usd_oracle_address != address(0), "Zero address detected"); // priceFeedETHUSD = AggregatorV3Interface(_eth_usd_oracle_address); // } function fraxPerLPToken() public view override returns (uint256 frax_per_lp_token) { // COMMENTED OUT SO COMPILER DOESNT COMPLAIN. UNCOMMENT WHEN DEPLOYING // Aura / Balancer frxETH-pxETH // ============================================ // { // // Get the pool ID // bytes32 _poolId = bal_vanilla_lp_tkn.getPoolId(); // // Get the balances of each token in the pool // ( , uint256[] memory balances, ) = bal_vanilla_vault.getPoolTokens(_poolId); // uint256 frxETH_in_pool = balances[1]; // uint256 frxETH_usd_value_e36 = (1e10) * (frxETH_in_pool * uint256(getLatestETHPriceE8())); // // Calculate the frxETH value per "actual" LP // // Balancer vault to Aura deposit vault is 1:1 // frax_per_lp_token = (frxETH_usd_value_e36) / bal_vanilla_lp_tkn.getActualSupply(); // } // Bunni FRAX/USDC Gauge // ============================================ // { // // Get the BunniKey so you can query the lens // IBunniLens.BunniKey memory bkey = IBunniLens.BunniKey({ // pool: univ3_pool, // tickLower: lp_tkn.tickLower(), // tickUpper: lp_tkn.tickUpper() // }); // (, uint256 amt0, uint256 amt1) = lens.pricePerFullShare(bkey); // // Calc FRAX per LP // if (frax_is_token0) frax_per_lp_token = amt0; // else frax_per_lp_token = amt1; // } // Morpho // ============================================ { // Convert 1e18 shares to FRAX frax_per_lp_token = stakingToken.convertToAssets(1e18); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"internalType":"address[]","name":"_rewardManagers","type":"address[]"},{"internalType":"uint256[]","name":"_rewardRates","type":"uint256[]"},{"internalType":"address[]","name":"_gaugeControllers","type":"address[]"},{"internalType":"address[]","name":"_rewardDistributors","type":"address[]"},{"internalType":"address","name":"_stakingToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedAdditional","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"new_secs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_start_ts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_end_ts","type":"uint256"}],"name":"LockedLonger","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token_address","type":"address"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secs","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"source_address","type":"address"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"WithdrawLocked","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"calcCurCombinedWeight","outputs":[{"internalType":"uint256","name":"old_combined_weight","type":"uint256"},{"internalType":"uint256","name":"new_vefxs_multiplier","type":"uint256"},{"internalType":"uint256","name":"new_combined_weight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"stake_idx","type":"uint256"}],"name":"calcCurrLockMultiplier","outputs":[{"internalType":"uint256","name":"midpoint_lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"address","name":"new_manager_address","type":"address"}],"name":"changeTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"combinedWeightOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"new_earned","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"farm_type","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPToken","outputs":[{"internalType":"uint256","name":"frax_per_lp_token","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getProxyFor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getReward","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_extra_too","type":"bool"}],"name":"getReward2","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getRewardExtraLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256[]","name":"rewards_per_duration_arr","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller_addr","type":"address"},{"internalType":"address","name":"reward_token_addr","type":"address"}],"name":"isTokenManagerFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRewardClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"addl_liq","type":"uint256"}],"name":"lockAdditional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"new_ending_ts","type":"uint256"}],"name":"lockLonger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"lockMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_for_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedLiquidityOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedStakes","outputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOf","outputs":[{"components":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"internalType":"struct FraxUnifiedFarm_ERC20.LockedStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOfLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"maxLPForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"minVeFXSForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"minVeFXSForMaxBoostProxy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"proxyStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"}],"name":"proxyToggleStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxy_lp_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token_idx","type":"uint256"}],"name":"rewardRates","outputs":[{"internalType":"uint256","name":"rwd_rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint256[]","name":"newRewardsPerTokenStored","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[6]","name":"_misc_vars","type":"uint256[6]"}],"name":"setMiscVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalsPaused","type":"bool"},{"internalType":"bool","name":"_rewardsCollectionPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalOnlyShutdown","type":"bool"}],"name":"setPauses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"uint256","name":"_new_rate","type":"uint256"},{"internalType":"address","name":"_gauge_controller_address","type":"address"},{"internalType":"address","name":"_rewards_distributor_address","type":"address"}],"name":"setRewardVars","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"stakeLocked","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"stakerSetVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"staker_designated_proxies","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakesUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IMetaMorpho","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"force_update","type":"bool"}],"name":"sync_gauge_weights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy_addr","type":"address"}],"name":"toggleValidVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalCombinedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLiquidityLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"userStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"veFXSMultiplier","outputs":[{"internalType":"uint256","name":"vefxs_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_boost_scale_factor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_per_frax_for_max_boost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_rewards_deprecated","type":"bool"}],"name":"withdrawLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalOnlyShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
671bc16d674ec8000060068190556305a39a806007556001600855673782dace9d9000006009819055600a91909155600b5560c06040526005608090815264189718171b60d91b60a052602390620000589082620005c3565b5060408051808201909152601281527122a92199182fa1b7b73b32bc2fa7ba3432b960711b6020820152602690620000919082620005c3565b503480156200009f57600080fd5b5060405162005c2f38038062005c2f833981016040819052620000c291620007eb565b86868686868686868686868686856001600160a01b0381166200012b5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600160025584516200019d9060109060208801906200045d565b508151620001b39060119060208501906200045d565b508051620001c99060129060208401906200045d565b508251620001df906013906020860190620004c7565b5060005b855181101562000393578060156000888481518110620002075762000207620008f2565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506001601460008884815181106200024e576200024e620008f2565b6020908102919091018101516001600160a01b031682528101919091526040016000908120805460ff191692151592909217909155601680546001810182559082527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901558451859082908110620002ca57620002ca620008f2565b6020026020010151600f6000888481518110620002eb57620002eb620008f2565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b03191693909216929092179055601a805460018181019092557f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01829055601b805480830182559083527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc1019190915501620001e3565b506022805460ff19169055426005556040805163513872bd60e01b81529051733669c421b77340b2979d1a00a792cc2ee0fce7379163513872bd9160048083019260209291908290030181865afa158015620003f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000419919062000908565b6004555050602480546001600160a01b03909d1661010002610100600160a81b0319909d169c909c17909b5550620009229f50505050505050505050505050505050565b828054828255906000526020600020908101928215620004b5579160200282015b82811115620004b557825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200047e565b50620004c392915062000505565b5090565b828054828255906000526020600020908101928215620004b5579160200282015b82811115620004b5578251825591602001919060010190620004e8565b5b80821115620004c3576000815560010162000506565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200054757607f821691505b6020821081036200056857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005be576000816000526020600020601f850160051c81016020861015620005995750805b601f850160051c820191505b81811015620005ba57828155600101620005a5565b5050505b505050565b81516001600160401b03811115620005df57620005df6200051c565b620005f781620005f0845462000532565b846200056e565b602080601f8311600181146200062f5760008415620006165750858301515b600019600386901b1c1916600185901b178555620005ba565b600085815260208120601f198616915b8281101562000660578886015182559484019460019091019084016200063f565b50858210156200067f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b0381168114620006a757600080fd5b919050565b604051601f8201601f191681016001600160401b0381118282101715620006d757620006d76200051c565b604052919050565b60006001600160401b03821115620006fb57620006fb6200051c565b5060051b60200190565b600082601f8301126200071757600080fd5b81516020620007306200072a83620006df565b620006ac565b8083825260208201915060208460051b8701019350868411156200075357600080fd5b602086015b848110156200077a576200076c816200068f565b835291830191830162000758565b509695505050505050565b600082601f8301126200079757600080fd5b81516020620007aa6200072a83620006df565b8083825260208201915060208460051b870101935086841115620007cd57600080fd5b602086015b848110156200077a5780518352918301918301620007d2565b600080600080600080600060e0888a0312156200080757600080fd5b62000812886200068f565b60208901519097506001600160401b03808211156200083057600080fd5b6200083e8b838c0162000705565b975060408a01519150808211156200085557600080fd5b620008638b838c0162000705565b965060608a01519150808211156200087a57600080fd5b620008888b838c0162000785565b955060808a01519150808211156200089f57600080fd5b620008ad8b838c0162000705565b945060a08a0151915080821115620008c457600080fd5b50620008d38a828b0162000705565b925050620008e460c089016200068f565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200091b57600080fd5b5051919050565b6152fd80620009326000396000f3fe608060405234801561001057600080fd5b50600436106104055760003560e01c80637f472e541161021a578063d2010fb411610135578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109a8578063facefb64146109bb578063fff6cae9146109ce57600080fd5b8063f2a8d3491461098c578063f2caeb1e1461099557600080fd5b8063e1ba95d21461095f578063e7f3058214610967578063ebe2b12b1461097a578063f288baf61461098357600080fd5b8063d7400d5611610104578063d7400d56146108fb578063d9f96e8d1461090e578063de1a655114610944578063e01f62bf1461095757600080fd5b8063d2010fb4146108b9578063d2fbdc0d146108c2578063d42fc9b4146108d5578063d5e1a9c6146108e857600080fd5b8063aa1d4fce116101ad578063c35438261161017c578063c35438261461085e578063c8f33c9114610871578063ca6df29d1461087a578063cdc82e80146108b057600080fd5b8063aa1d4fce14610826578063b85efd061461082f578063b94c4dcb14610842578063c00007b01461084b57600080fd5b80638da5cb5b116101e95780638da5cb5b146107d357806391cf600a146107f35780639637927f14610806578063a0f234761461081357600080fd5b80637f472e541461076a5780638980f11f1461077d57806389b5f00b146107905780638bad86a7146107a557600080fd5b806341a16f3f116103255780636c430dbb116102b8578063774d4ae7116102875780637970833e1161026c5780637970833e1461070857806379ba5097146107435780637d6ef08e1461074b57600080fd5b8063774d4ae7146106e25780637910d17b146106f557600080fd5b80636c430dbb1461068c5780636e27cef9146106ac57806370641a36146106b557806372f702f3146106bd57600080fd5b806354fd4d50116102f457806354fd4d50146106545780635bfd92581461065c57806364f2c06014610664578063693392451461066c57600080fd5b806341a16f3f146105d657806341edbdf01461060c5780634fd2b5361461062157806353a47bb71461063457600080fd5b80631face8561161039d5780632df079f11161036c5780632df079f11461057057806336f89af214610583578063386a9525146105b9578063387edc86146105c357600080fd5b80631face856146104cc578063231b68dc146104df57806328408bab146105025780632c0c2a0a1461055d57600080fd5b80631627540c116103d95780631627540c1461047c57806317b18c89146104915780631c1f78eb146104a45780631e090f01146104ac57600080fd5b80628cc2621461040a5780630238b936146104335780630d7bac4f1461045457806312edb24c14610467575b600080fd5b61041d610418366004614ce7565b6109d6565b60405161042a9190614d02565b60405180910390f35b610446610441366004614d54565b610b4b565b60405190815260200161042a565b610446610462366004614d94565b610c4c565b61046f610c78565b60405161042a9190614dad565b61048f61048a366004614ce7565b610ce7565b005b61044661049f366004614dfb565b610e07565b61041d610e91565b6104bf6104ba366004614ce7565b610f28565b60405161042a9190614e1d565b6104466104da366004614ce7565b610fdc565b6104f26104ed366004614e8b565b611021565b604051901515815260200161042a565b610538610510366004614ce7565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161042a565b61044661056b366004614ce7565b611107565b61048f61057e366004614ebe565b6113f3565b610446610591366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61044662093a8081565b61048f6105d1366004614ce7565b61156c565b6105386105e4366004614ce7565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6106146116cb565b60405161042a9190614f3e565b61044661062f366004614ce7565b611759565b6001546105389073ffffffffffffffffffffffffffffffffffffffff1681565b61061461177a565b610446611787565b601d54610446565b61044661067a366004614ce7565b60156020526000908152604090205481565b61044661069a366004614ce7565b60196020526000908152604090205481565b61044660085481565b61041d61182c565b60245461053890610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6104466106f0366004614f8f565b611981565b61041d610703366004614fb9565b611b8d565b61071b610716366004614f8f565b611c09565b604080519586526020860194909452928401919091526060830152608082015260a00161042a565b61048f611c57565b610446610759366004614ce7565b602080526000908152604090205481565b610446610778366004614ce7565b611da2565b61048f61078b366004614f8f565b611db9565b6022546104f290640100000000900460ff1681565b6107b86107b3366004614ce7565b611f4a565b6040805193845260208401929092529082015260600161042a565b6000546105389073ffffffffffffffffffffffffffffffffffffffff1681565b61048f610801366004614ce7565b612177565b6022546104f29060ff1681565b610446610821366004614ce7565b61226a565b61044660095481565b61048f61083d366004614dfb565b612334565b61044660075481565b61041d610859366004614ce7565b6125d0565b61053861086c366004614ce7565b612658565b61044660055481565b610446610888366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526025602052604090205490565b61044660065481565b61044660035481565b61048f6108d0366004614dfb565b6126bb565b6104466108e3366004614ce7565b612b08565b61048f6108f6366004614ff0565b612b44565b61048f610909366004614ce7565b612d33565b61044661091c366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61048f610952366004614e8b565b612f4d565b601c54610446565b61048f613034565b61048f610975366004614ce7565b613105565b61044660045481565b610446600a5481565b610446600b5481565b6104466109a3366004614d94565b613265565b61048f6109b636600461503d565b61337c565b61048f6109c9366004615089565b613548565b61048f613708565b606060006109e261182c565b60105490915067ffffffffffffffff811115610a0057610a0061505a565b604051908082528060200260200182016040528015610a29578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610b455760005b601054811015610b435773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610ac857610ac861512e565b6020026020010151610ada919061518c565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b0a919061519f565b610b1491906151b6565b610b1e91906151f1565b838281518110610b3057610b3061512e565b6020908102919091010152600101610a5b565b505b50919050565b60006002805403610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610bb4565b610c3f338486856137ad565b6001600255949350505050565b600654600754600091610c7291610c63828661519f565b610c6d91906151b6565b61396c565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610cdd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610cb2575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610bb4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610e74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055610e853380858542613984565b60016002559392505050565b60135460609067ffffffffffffffff811115610eaf57610eaf61505a565b604051908082528060200260200182016040528015610ed8578160200160208202803683370190505b50905060005b601354811015610f245762093a80610ef582613265565b610eff919061519f565b828281518110610f1157610f1161512e565b6020908102919091010152600101610ede565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602560209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610fd157838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610f6d565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a7640000916110179161519f565b610c7291906151b6565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff1661105657506000610c72565b73ffffffffffffffffffffffffffffffffffffffff8316158061108d575073ffffffffffffffffffffffffffffffffffffffff8216155b1561109a57506000610c72565b60005473ffffffffffffffffffffffffffffffffffffffff908116908416036110c557506001610c72565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f60205260409020548185169116036110fe57506001610c72565b50600092915050565b6000808061111484612658565b905073ffffffffffffffffffffffffffffffffffffffff8116156111d9576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156111b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d49190615204565b61127b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127b9190615204565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b9190615204565b611315919061519f565b600954600a54611325908661519f565b61132f919061519f565b61133991906151b6565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156113685761136384611da2565b611371565b61137187611759565b905080156113c35760008161138e670de0b6b3a76400008861519f565b61139891906151b6565b9050670de0b6b3a7640000600a54826113b1919061519f565b6113bb91906151b6565b9250506113c8565b600091505b508082116113d657806113d8565b815b9450600a548511156113ea57600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061142c5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611492576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115315750602254640100000000900460ff16155b1561156657602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b60028054036115d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055602254640100000000900460ff1615611650576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b60225462010000900460ff16156116c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610bb4565b506001600255565b602680546116d89061521d565b80601f01602080910402602001604051908101604052809291908181526020018280546117049061521d565b80156117515780601f1061172657610100808354040283529160200191611751565b820191906000526020600020905b81548152906001019060200180831161173457829003601f168201915b505050505081565b6000670de0b6b3a7640000600b5461177084612b08565b611017919061519f565b602380546116d89061521d565b602480546040517f07a2d13a000000000000000000000000000000000000000000000000000000008152670de0b6b3a7640000600482015260009261010090920473ffffffffffffffffffffffffffffffffffffffff16916307a2d13a9101602060405180830381865afa158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615204565b905090565b6060601c546000148061183f5750601d54155b15611899576016805480602002602001604051908101604052809291908181526020018280548015610cdd57602002820191906000526020600020905b81548152602001906001019080831161187c575050505050905090565b60105467ffffffffffffffff8111156118b4576118b461505a565b6040519080825280602002602001820160405280156118dd578160200160208202803683370190505b50905060005b601654811015610f2457601d546118f982613265565b600554611904613d48565b61190e919061518c565b611918919061519f565b61192a90670de0b6b3a764000061519f565b61193491906151b6565b601682815481106119475761194761512e565b906000526020600020015461195c91906151f1565b82828151811061196e5761196e61512e565b60209081029190910101526001016118e3565b73ffffffffffffffffffffffffffffffffffffffff821660009081526025602052604081208054829190849081106119bb576119bb61512e565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611a3957506020810151611a61565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611b2157606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611b18576000818360600151611aaf919061518c565b90506000836060015142611ac3919061518c565b90506000611ad56104626002856151b6565b90506000611ae3838261519f565b611aed858461519f565b611af791906151f1565b9050611b0383856151f1565b611b0d90826151b6565b965050505050611b71565b60009250611b71565b600080828460600151611b34919061518c565b90506000428560600151611b48919061518c565b90506002611b5682846151f1565b611b6091906151b6565b92505050611b6d81610c4c565b9350505b8160800151831115611b8557816080015192505b505092915050565b60606002805403611bfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055610e85338484613d56565b60256020528160005260406000208181548110611c2557600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610bb4565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b5461177084610fdc565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611de65750611de63382611021565b611e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff16808015611ea8575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ed3575080158015611ed3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611ee35761156684338561408f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610bb4565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080611f7b84611107565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e602052604081205491935090158015611fd5575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b80612005575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15612011575081612051565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090205460029061204490856151f1565b61204e91906151b6565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff861660009081526025602052604090205481101561216e5773ffffffffffffffffffffffffffffffffffffffff861660009081526025602052604081208054839081106120bc576120bc61512e565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006121158884611981565b60408301519091506000670de0b6b3a764000061213287856151f1565b61213c908461519f565b61214691906151b6565b61215090836151f1565b905061215c81886151f1565b96505060019093019250612058915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806121b05750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461227c919061519f565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612306573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232a9190615204565b611770919061519f565b600280540361239f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b600280556022546301000000900460ff1615612417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b602254640100000000900460ff161561248c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b61249833336001613d56565b506000806124a633856141ff565b9150915060008383604001516124bc91906151f1565b90506024546124e890610100900473ffffffffffffffffffffffffffffffffffffffff163330876143cd565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260259091529190912080548490811061253a5761253a61512e565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506125893385600161456b565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6060600280540361263d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b6002805561264d33836001613d56565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff161561268a575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612726576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b600280556022546301000000900460ff161561279e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b602254640100000000900460ff1615612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b61281f33336001613d56565b5060008061282d33856141ff565b9150915042831161289a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610bb4565b6000428360600151116128ae5760006128be565b4283606001516128be919061518c565b905060006128cc428661518c565b9050818111612937576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610bb4565b6008548110156129a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610bb4565b600754811115612a0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610bb4565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612a3f83610c4c565b9052336000908152602560205260409020805485908110612a6257612a6261512e565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612ab233600060016146da565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a7640000916110179161519f565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612b715750612b713382611021565b612bd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054601380548692908110612c1257612c1261512e565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612c7357612c7361512e565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260159091526040902054601280548492908110612ce457612ce461512e565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610bb4565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ed057336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff851684529180528220805491929091612eca90849061518c565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091612f449084906151f1565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612f7a5750612f7a3382611021565b612fe0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061306d5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6130d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff1661317e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610bb4565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036132625773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161325c90849061518c565b90915550505b50565b6000806011838154811061327b5761327b61512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561335657670de0b6b3a7640000601a84815481106132c1576132c161512e565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613317573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061333b9190615204565b613345919061519f565b61334f91906151b6565b9150610b45565b601383815481106133695761336961512e565b9060005260206000200154915050919050565b60005b6011548110156135445760006011828154811061339e5761339e61512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561353b5782806133f05750601b82815481106133e2576133e261512e565b906000526020600020015442115b1561353b576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348b9190615204565b601a838154811061349e5761349e61512e565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351b9190615204565b601b838154811061352e5761352e61512e565b6000918252602090912001555b5060010161337f565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806135815750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6135e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b8051670de0b6b3a7640000111561365a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610bb4565b6080810151600111801590613674575060a0810151600111155b6136da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610bb4565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff161561377d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b613787600061337c565b61378f611787565b60035560045442106137a5576137a3614859565b565b6137a3614b6e565b602254600090640100000000900460ff166137d0576137ce85856001613d56565b505b6000806137dd87866141ff565b915091508160600151421015806137fb575060225460ff1615156001145b613861576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610bb4565b604082015180156139615760245461389590610100900473ffffffffffffffffffffffffffffffffffffffff16888361408f565b73ffffffffffffffffffffffffffffffffffffffff881660009081526025602052604090208054839081106138cc576138cc61512e565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613906908990839061456b565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b600081831061397b578161397d565b825b9392505050565b6000856001613995828260006146da565b602254640100000000900460ff1615613a0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b6022546301000000900460ff1615613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b600854851015613aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610bb4565b600754851115613b56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610bb4565b602454613b8090610100900473ffffffffffffffffffffffffffffffffffffffff168830896143cd565b6000613b8b86610c4c565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526025835283902060a0850184528185529184018a90529183018b90529092509060608101613c7e8a8a6151f1565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613cda908b908a9061456b565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006118274260045461396c565b6060836001613d67828260006146da565b602254640100000000900460ff1615613ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b60225462010000900460ff1615613e4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff811115613e9257613e9261505a565b604051908082528060200260200182016040528015613ebb578160200160208202803683370190505b50925060005b6010548110156140855773ffffffffffffffffffffffffffffffffffffffff871660009081526018602090815260408083208484529091529020548451859083908110613f1057613f1061512e565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526018825260408082208483529092529081208190558451859083908110613f6457613f6461512e565b6020026020010151111561407d57613fd360108281548110613f8857613f8861512e565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613fc657613fc661512e565b602002602001015161408f565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061401d5761401d61512e565b6020026020010151601084815481106140385761403861512e565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101613ec1565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614126919061526a565b6000604051808303816000865af19150503d8060008114614163576040519150601f19603f3d011682016040523d82523d6000602084013e614168565b606091505b50915091508180156141925750805115806141925750808060200190518101906141929190615286565b6141f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610bb4565b5050505050565b6142346040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156143515760005b73ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090205481101561434f5773ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090208054829081106142a3576142a361512e565b90600052602060002090600502016000015484036143475773ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090208054829081106142f2576142f261512e565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050925080915061434f565b60010161423f565b505b82158015906143605750815183145b6143c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610bb4565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161446c919061526a565b6000604051808303816000865af19150503d80600081146144a9576040519150601f19603f3d011682016040523d82523d6000602084013e6144ae565b606091505b50915091508180156144d85750805115806144d85750808060200190518101906144d89190615286565b614563576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610bb4565b505050505050565b600061457684612658565b9050811561462a5782601c600082825461459091906151f1565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906145ca9084906151f1565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156146255773ffffffffffffffffffffffffffffffffffffffff811660009081526020805260408120805485929061461f9084906151f1565b90915550505b6146d1565b82601c600082825461463c919061518c565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e60205260408120805485929061467690849061518c565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156146d15773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548592906146cb90849061518c565b90915550505b61156684600060015b602254640100000000900460ff166146fa5781156146fa576146fa613708565b80156147305761470983611107565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff831615611f4557600080600061475a86611f4a565b6022549295509093509150640100000000900460ff1661477d5761477d86614bd7565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c602052604090208290558281106148015760006147b8848361518c565b905080601d546147c891906151f1565b601d556147d581856151f1565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550614563565b600061480d828561518c565b905080601d5461481d919061518c565b601d5561482a818561518c565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614861614b6e565b60005b601254811015614948576000601282815481106148835761488361512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561493f576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061493c91906152a3565b50505b50600101614864565b50600062093a806004544261495d919061518c565b61496791906151b6565b905060005b601054811015614b4057601081815481106149895761498961512e565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a249190615204565b614a2f8360016151f1565b62093a80614a3c84613265565b614a46919061519f565b614a50919061519f565b111560108281548110614a6557614a6561512e565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb49190614f3e565b5060010161496c565b5062093a80614b508260016151f1565b614b5a919061519f565b600454614b6791906151f1565b6004556132625b6000614b7861182c565b905060005b601654811015614bc857818181518110614b9957614b9961512e565b602002602001015160168281548110614bb457614bb461512e565b600091825260209091200155600101614b7d565b50614bd1613d48565b60055550565b73ffffffffffffffffffffffffffffffffffffffff811615613262576000614bfe826109d6565b905060005b8151811015614c6257818181518110614c1e57614c1e61512e565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101614c03565b5060005b8151811015611f455760168181548110614c8257614c8261512e565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff86168352601782526040808420858552909252912055600101614c66565b803573ffffffffffffffffffffffffffffffffffffffff811681146126b657600080fd5b600060208284031215614cf957600080fd5b61397d82614cc3565b6020808252825182820181905260009190848201906040850190845b81811015614d3a57835183529284019291840191600101614d1e565b50909695505050505050565b801515811461326257600080fd5b600080600060608486031215614d6957600080fd5b83359250614d7960208501614cc3565b91506040840135614d8981614d46565b809150509250925092565b600060208284031215614da657600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d3a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614dc9565b60008060408385031215614e0e57600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e7e5781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614e3a565b5091979650505050505050565b60008060408385031215614e9e57600080fd5b614ea783614cc3565b9150614eb560208401614cc3565b90509250929050565b60008060008060808587031215614ed457600080fd5b8435614edf81614d46565b93506020850135614eef81614d46565b92506040850135614eff81614d46565b91506060850135614f0f81614d46565b939692955090935050565b60005b83811015614f35578181015183820152602001614f1d565b50506000910152565b6020815260008251806020840152614f5d816040850160208701614f1a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614fa257600080fd5b614fab83614cc3565b946020939093013593505050565b60008060408385031215614fcc57600080fd5b614fd583614cc3565b91506020830135614fe581614d46565b809150509250929050565b6000806000806080858703121561500657600080fd5b61500f85614cc3565b93506020850135925061502460408601614cc3565b915061503260608601614cc3565b905092959194509250565b60006020828403121561504f57600080fd5b813561397d81614d46565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561509b57600080fd5b82601f8301126150aa57600080fd5b60405160c0810181811067ffffffffffffffff821117156150f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561510957600080fd5b845b8181101561512357803583526020928301920161510b565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610c7257610c7261515d565b8082028115828204841417610c7257610c7261515d565b6000826151ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610c7257610c7261515d565b60006020828403121561521657600080fd5b5051919050565b600181811c9082168061523157607f821691505b602082108103610b45577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000825161527c818460208701614f1a565b9190910192915050565b60006020828403121561529857600080fd5b815161397d81614d46565b600080604083850312156152b657600080fd5b50508051602090910151909290915056fea2646970667358221220136292d73fa0d5c1542e8129b18b22e0bee7d83eb30bc7f086ae0148341aa9ab64736f6c63430008170033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000be40491f3261fd42724f1aeb465796eb11c06ddf00000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104055760003560e01c80637f472e541161021a578063d2010fb411610135578063e1ba95d2116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109a8578063facefb64146109bb578063fff6cae9146109ce57600080fd5b8063f2a8d3491461098c578063f2caeb1e1461099557600080fd5b8063e1ba95d21461095f578063e7f3058214610967578063ebe2b12b1461097a578063f288baf61461098357600080fd5b8063d7400d5611610104578063d7400d56146108fb578063d9f96e8d1461090e578063de1a655114610944578063e01f62bf1461095757600080fd5b8063d2010fb4146108b9578063d2fbdc0d146108c2578063d42fc9b4146108d5578063d5e1a9c6146108e857600080fd5b8063aa1d4fce116101ad578063c35438261161017c578063c35438261461085e578063c8f33c9114610871578063ca6df29d1461087a578063cdc82e80146108b057600080fd5b8063aa1d4fce14610826578063b85efd061461082f578063b94c4dcb14610842578063c00007b01461084b57600080fd5b80638da5cb5b116101e95780638da5cb5b146107d357806391cf600a146107f35780639637927f14610806578063a0f234761461081357600080fd5b80637f472e541461076a5780638980f11f1461077d57806389b5f00b146107905780638bad86a7146107a557600080fd5b806341a16f3f116103255780636c430dbb116102b8578063774d4ae7116102875780637970833e1161026c5780637970833e1461070857806379ba5097146107435780637d6ef08e1461074b57600080fd5b8063774d4ae7146106e25780637910d17b146106f557600080fd5b80636c430dbb1461068c5780636e27cef9146106ac57806370641a36146106b557806372f702f3146106bd57600080fd5b806354fd4d50116102f457806354fd4d50146106545780635bfd92581461065c57806364f2c06014610664578063693392451461066c57600080fd5b806341a16f3f146105d657806341edbdf01461060c5780634fd2b5361461062157806353a47bb71461063457600080fd5b80631face8561161039d5780632df079f11161036c5780632df079f11461057057806336f89af214610583578063386a9525146105b9578063387edc86146105c357600080fd5b80631face856146104cc578063231b68dc146104df57806328408bab146105025780632c0c2a0a1461055d57600080fd5b80631627540c116103d95780631627540c1461047c57806317b18c89146104915780631c1f78eb146104a45780631e090f01146104ac57600080fd5b80628cc2621461040a5780630238b936146104335780630d7bac4f1461045457806312edb24c14610467575b600080fd5b61041d610418366004614ce7565b6109d6565b60405161042a9190614d02565b60405180910390f35b610446610441366004614d54565b610b4b565b60405190815260200161042a565b610446610462366004614d94565b610c4c565b61046f610c78565b60405161042a9190614dad565b61048f61048a366004614ce7565b610ce7565b005b61044661049f366004614dfb565b610e07565b61041d610e91565b6104bf6104ba366004614ce7565b610f28565b60405161042a9190614e1d565b6104466104da366004614ce7565b610fdc565b6104f26104ed366004614e8b565b611021565b604051901515815260200161042a565b610538610510366004614ce7565b60216020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161042a565b61044661056b366004614ce7565b611107565b61048f61057e366004614ebe565b6113f3565b610446610591366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205490565b61044662093a8081565b61048f6105d1366004614ce7565b61156c565b6105386105e4366004614ce7565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6106146116cb565b60405161042a9190614f3e565b61044661062f366004614ce7565b611759565b6001546105389073ffffffffffffffffffffffffffffffffffffffff1681565b61061461177a565b610446611787565b601d54610446565b61044661067a366004614ce7565b60156020526000908152604090205481565b61044661069a366004614ce7565b60196020526000908152604090205481565b61044660085481565b61041d61182c565b60245461053890610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6104466106f0366004614f8f565b611981565b61041d610703366004614fb9565b611b8d565b61071b610716366004614f8f565b611c09565b604080519586526020860194909452928401919091526060830152608082015260a00161042a565b61048f611c57565b610446610759366004614ce7565b602080526000908152604090205481565b610446610778366004614ce7565b611da2565b61048f61078b366004614f8f565b611db9565b6022546104f290640100000000900460ff1681565b6107b86107b3366004614ce7565b611f4a565b6040805193845260208401929092529082015260600161042a565b6000546105389073ffffffffffffffffffffffffffffffffffffffff1681565b61048f610801366004614ce7565b612177565b6022546104f29060ff1681565b610446610821366004614ce7565b61226a565b61044660095481565b61048f61083d366004614dfb565b612334565b61044660075481565b61041d610859366004614ce7565b6125d0565b61053861086c366004614ce7565b612658565b61044660055481565b610446610888366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526025602052604090205490565b61044660065481565b61044660035481565b61048f6108d0366004614dfb565b6126bb565b6104466108e3366004614ce7565b612b08565b61048f6108f6366004614ff0565b612b44565b61048f610909366004614ce7565b612d33565b61044661091c366004614ce7565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61048f610952366004614e8b565b612f4d565b601c54610446565b61048f613034565b61048f610975366004614ce7565b613105565b61044660045481565b610446600a5481565b610446600b5481565b6104466109a3366004614d94565b613265565b61048f6109b636600461503d565b61337c565b61048f6109c9366004615089565b613548565b61048f613708565b606060006109e261182c565b60105490915067ffffffffffffffff811115610a0057610a0061505a565b604051908082528060200260200182016040528015610a29578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601f602052604090205490925015610b455760005b601054811015610b435773ffffffffffffffffffffffffffffffffffffffff84166000818152601860209081526040808320858452825280832054938352601782528083208584529091529020548351670de0b6b3a76400009190859085908110610ac857610ac861512e565b6020026020010151610ada919061518c565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601f6020526040902054610b0a919061519f565b610b1491906151b6565b610b1e91906151f1565b838281518110610b3057610b3061512e565b6020908102919091010152600101610a5b565b505b50919050565b60006002805403610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60028055602254610100900460ff1615610c33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610bb4565b610c3f338486856137ad565b6001600255949350505050565b600654600754600091610c7291610c63828661519f565b610c6d91906151b6565b61396c565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610cdd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610cb2575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610bb4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610e74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055610e853380858542613984565b60016002559392505050565b60135460609067ffffffffffffffff811115610eaf57610eaf61505a565b604051908082528060200260200182016040528015610ed8578160200160208202803683370190505b50905060005b601354811015610f245762093a80610ef582613265565b610eff919061519f565b828281518110610f1157610f1161512e565b6020908102919091010152600101610ede565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602560209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610fd157838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610f6d565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812054600354670de0b6b3a7640000916110179161519f565b610c7291906151b6565b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604081205460ff1661105657506000610c72565b73ffffffffffffffffffffffffffffffffffffffff8316158061108d575073ffffffffffffffffffffffffffffffffffffffff8216155b1561109a57506000610c72565b60005473ffffffffffffffffffffffffffffffffffffffff908116908416036110c557506001610c72565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f60205260409020548185169116036110fe57506001610c72565b50600092915050565b6000808061111484612658565b905073ffffffffffffffffffffffffffffffffffffffff8116156111d9576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa1580156111b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d49190615204565b61127b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015611257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127b9190615204565b91506000670de0b6b3a764000073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b9190615204565b611315919061519f565b600954600a54611325908661519f565b61132f919061519f565b61133991906151b6565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156113685761136384611da2565b611371565b61137187611759565b905080156113c35760008161138e670de0b6b3a76400008861519f565b61139891906151b6565b9050670de0b6b3a7640000600a54826113b1919061519f565b6113bb91906151b6565b9250506113c8565b600091505b508082116113d657806113d8565b815b9450600a548511156113ea57600a5494505b50505050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061142c5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611492576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff166301000000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000841515021790558080156115315750602254640100000000900460ff16155b1561156657602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555b50505050565b60028054036115d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055602254640100000000900460ff1615611650576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b60225462010000900460ff16156116c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610bb4565b506001600255565b602680546116d89061521d565b80601f01602080910402602001604051908101604052809291908181526020018280546117049061521d565b80156117515780601f1061172657610100808354040283529160200191611751565b820191906000526020600020905b81548152906001019060200180831161173457829003601f168201915b505050505081565b6000670de0b6b3a7640000600b5461177084612b08565b611017919061519f565b602380546116d89061521d565b602480546040517f07a2d13a000000000000000000000000000000000000000000000000000000008152670de0b6b3a7640000600482015260009261010090920473ffffffffffffffffffffffffffffffffffffffff16916307a2d13a9101602060405180830381865afa158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615204565b905090565b6060601c546000148061183f5750601d54155b15611899576016805480602002602001604051908101604052809291908181526020018280548015610cdd57602002820191906000526020600020905b81548152602001906001019080831161187c575050505050905090565b60105467ffffffffffffffff8111156118b4576118b461505a565b6040519080825280602002602001820160405280156118dd578160200160208202803683370190505b50905060005b601654811015610f2457601d546118f982613265565b600554611904613d48565b61190e919061518c565b611918919061519f565b61192a90670de0b6b3a764000061519f565b61193491906151b6565b601682815481106119475761194761512e565b906000526020600020015461195c91906151f1565b82828151811061196e5761196e61512e565b60209081029190910101526001016118e3565b73ffffffffffffffffffffffffffffffffffffffff821660009081526025602052604081208054829190849081106119bb576119bb61512e565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff8916855260199092528320549193501115611a3957506020810151611a61565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601960205260409020545b42826060015111611b2157606082015173ffffffffffffffffffffffffffffffffffffffff86166000908152601960205260409020541015611b18576000818360600151611aaf919061518c565b90506000836060015142611ac3919061518c565b90506000611ad56104626002856151b6565b90506000611ae3838261519f565b611aed858461519f565b611af791906151f1565b9050611b0383856151f1565b611b0d90826151b6565b965050505050611b71565b60009250611b71565b600080828460600151611b34919061518c565b90506000428560600151611b48919061518c565b90506002611b5682846151f1565b611b6091906151b6565b92505050611b6d81610c4c565b9350505b8160800151831115611b8557816080015192505b505092915050565b60606002805403611bfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60028055610e85338484613d56565b60256020528160005260406000208181548110611c2557600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610bb4565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b5461177084610fdc565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611de65750611de63382611021565b611e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff831660009081526014602052604090205460ff16808015611ea8575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ed3575080158015611ed3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611ee35761156684338561408f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610bb4565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f60205260408120549080611f7b84611107565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601e602052604081205491935090158015611fd5575073ffffffffffffffffffffffffffffffffffffffff85166000908152601f6020526040902054155b80612005575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15612011575081612051565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090205460029061204490856151f1565b61204e91906151b6565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff861660009081526025602052604090205481101561216e5773ffffffffffffffffffffffffffffffffffffffff861660009081526025602052604081208054839081106120bc576120bc61512e565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006121158884611981565b60408301519091506000670de0b6b3a764000061213287856151f1565b61213c908461519f565b61214691906151b6565b61215090836151f1565b905061215c81886151f1565b96505060019093019250612058915050565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff163314806121b05750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461227c919061519f565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152670de0b6b3a764000090819073c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0906370a0823190602401602060405180830381865afa158015612306573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232a9190615204565b611770919061519f565b600280540361239f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b600280556022546301000000900460ff1615612417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b602254640100000000900460ff161561248c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b61249833336001613d56565b506000806124a633856141ff565b9150915060008383604001516124bc91906151f1565b90506024546124e890610100900473ffffffffffffffffffffffffffffffffffffffff163330876143cd565b6040805160a08101825286815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260259091529190912080548490811061253a5761253a61512e565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506125893385600161456b565b604080518681526020810186905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a250506001600255505050565b6060600280540361263d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b6002805561264d33836001613d56565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff161561268a575090565b5073ffffffffffffffffffffffffffffffffffffffff9081166000908152602160205260409020541690565b919050565b6002805403612726576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b600280556022546301000000900460ff161561279e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b602254640100000000900460ff1615612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b61281f33336001613d56565b5060008061282d33856141ff565b9150915042831161289a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610bb4565b6000428360600151116128ae5760006128be565b4283606001516128be919061518c565b905060006128cc428661518c565b9050818111612937576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610bb4565b6008548110156129a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610bb4565b600754811115612a0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610bb4565b6040518060a0016040528087815260200142815260200185604001518152602001868152602001612a3f83610c4c565b9052336000908152602560205260409020805485908110612a6257612a6261512e565b90600052602060002090600502016000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155905050612ab233600060016146da565b6040805187815260208101839052428183015260608101879052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a25050600160025550505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e6020526040812054600354670de0b6b3a7640000916110179161519f565b600054849073ffffffffffffffffffffffffffffffffffffffff16331480612b715750612b713382611021565b612bd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054601380548692908110612c1257612c1261512e565b9060005260206000200181905550826011601560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612c7357612c7361512e565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260159091526040902054601280548492908110612ce457612ce461512e565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610bb4565b3360009081526021602052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ed057336000908152601e602090815260408083205473ffffffffffffffffffffffffffffffffffffffff851684529180528220805491929091612eca90849061518c565b90915550505b33600090815260216020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601e8352818420549084529180528220805491929091612f449084906151f1565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612f7a5750612f7a3382611021565b612fe0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610bb4565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061306d5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6130d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b336000908152600d602052604090205460ff1661317e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610bb4565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560219092529091205416036132625773ffffffffffffffffffffffffffffffffffffffff8116600090815260216020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601e825280832054338452918052822080549192909161325c90849061518c565b90915550505b50565b6000806011838154811061327b5761327b61512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561335657670de0b6b3a7640000601a84815481106132c1576132c161512e565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa158015613317573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061333b9190615204565b613345919061519f565b61334f91906151b6565b9150610b45565b601383815481106133695761336961512e565b9060005260206000200154915050919050565b60005b6011548110156135445760006011828154811061339e5761339e61512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561353b5782806133f05750601b82815481106133e2576133e261512e565b906000526020600020015442115b1561353b576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af1158015613467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348b9190615204565b601a838154811061349e5761349e61512e565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351b9190615204565b601b838154811061352e5761352e61512e565b6000918252602090912001555b5060010161337f565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806135815750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6135e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610bb4565b8051670de0b6b3a7640000111561365a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610bb4565b6080810151600111801590613674575060a0810151600111155b6136da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610bb4565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b602254640100000000900460ff161561377d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b613787600061337c565b61378f611787565b60035560045442106137a5576137a3614859565b565b6137a3614b6e565b602254600090640100000000900460ff166137d0576137ce85856001613d56565b505b6000806137dd87866141ff565b915091508160600151421015806137fb575060225460ff1615156001145b613861576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610bb4565b604082015180156139615760245461389590610100900473ffffffffffffffffffffffffffffffffffffffff16888361408f565b73ffffffffffffffffffffffffffffffffffffffff881660009081526025602052604090208054839081106138cc576138cc61512e565b600091825260208220600590910201818155600181018290556002810182905560038101829055600401819055613906908990839061456b565b604080518281526020810188905273ffffffffffffffffffffffffffffffffffffffff898116828401529151918a16917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b979650505050505050565b600081831061397b578161397d565b825b9392505050565b6000856001613995828260006146da565b602254640100000000900460ff1615613a0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b6022546301000000900460ff1615613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610bb4565b600854851015613aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610bb4565b600754851115613b56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610bb4565b602454613b8090610100900473ffffffffffffffffffffffffffffffffffffffff168830896143cd565b6000613b8b86610c4c565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601e602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526025835283902060a0850184528185529184018a90529183018b90529092509060608101613c7e8a8a6151f1565b81526020908101859052825460018181018555600094855293829020835160059092020190815590820151818401556040820151600282015560608201516003820155608090910151600490910155613cda908b908a9061456b565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b60006118274260045461396c565b6060836001613d67828260006146da565b602254640100000000900460ff1615613ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79207769746864726177616c7320616c6c6f77656400000000000000006044820152606401610bb4565b60225462010000900460ff1615613e4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610bb4565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260196020526040902042905560105467ffffffffffffffff811115613e9257613e9261505a565b604051908082528060200260200182016040528015613ebb578160200160208202803683370190505b50925060005b6010548110156140855773ffffffffffffffffffffffffffffffffffffffff871660009081526018602090815260408083208484529091529020548451859083908110613f1057613f1061512e565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526018825260408082208483529092529081208190558451859083908110613f6457613f6461512e565b6020026020010151111561407d57613fd360108281548110613f8857613f8861512e565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613fc657613fc661512e565b602002602001015161408f565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff85838151811061401d5761401d61512e565b6020026020010151601084815481106140385761403861512e565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b600101613ec1565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614126919061526a565b6000604051808303816000865af19150503d8060008114614163576040519150601f19603f3d011682016040523d82523d6000602084013e614168565b606091505b50915091508180156141925750805115806141925750808060200190518101906141929190615286565b6141f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610bb4565b5050505050565b6142346040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b600082156143515760005b73ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090205481101561434f5773ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090208054829081106142a3576142a361512e565b90600052602060002090600502016000015484036143475773ffffffffffffffffffffffffffffffffffffffff851660009081526025602052604090208054829081106142f2576142f261512e565b90600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050925080915061434f565b60010161423f565b505b82158015906143605750815183145b6143c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610bb4565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161446c919061526a565b6000604051808303816000865af19150503d80600081146144a9576040519150601f19603f3d011682016040523d82523d6000602084013e6144ae565b606091505b50915091508180156144d85750805115806144d85750808060200190518101906144d89190615286565b614563576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610bb4565b505050505050565b600061457684612658565b9050811561462a5782601c600082825461459091906151f1565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e6020526040812080548592906145ca9084906151f1565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156146255773ffffffffffffffffffffffffffffffffffffffff811660009081526020805260408120805485929061461f9084906151f1565b90915550505b6146d1565b82601c600082825461463c919061518c565b909155505073ffffffffffffffffffffffffffffffffffffffff84166000908152601e60205260408120805485929061467690849061518c565b909155505073ffffffffffffffffffffffffffffffffffffffff8116156146d15773ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040812080548592906146cb90849061518c565b90915550505b61156684600060015b602254640100000000900460ff166146fa5781156146fa576146fa613708565b80156147305761470983611107565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260409020555b73ffffffffffffffffffffffffffffffffffffffff831615611f4557600080600061475a86611f4a565b6022549295509093509150640100000000900460ff1661477d5761477d86614bd7565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c602052604090208290558281106148015760006147b8848361518c565b905080601d546147c891906151f1565b601d556147d581856151f1565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550614563565b600061480d828561518c565b905080601d5461481d919061518c565b601d5561482a818561518c565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601f602052604090205550505050505050565b614861614b6e565b60005b601254811015614948576000601282815481106148835761488361512e565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561493f576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af1158015614918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061493c91906152a3565b50505b50600101614864565b50600062093a806004544261495d919061518c565b61496791906151b6565b905060005b601054811015614b4057601081815481106149895761498961512e565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015614a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a249190615204565b614a2f8360016151f1565b62093a80614a3c84613265565b614a46919061519f565b614a50919061519f565b111560108281548110614a6557614a6561512e565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb49190614f3e565b5060010161496c565b5062093a80614b508260016151f1565b614b5a919061519f565b600454614b6791906151f1565b6004556132625b6000614b7861182c565b905060005b601654811015614bc857818181518110614b9957614b9961512e565b602002602001015160168281548110614bb457614bb461512e565b600091825260209091200155600101614b7d565b50614bd1613d48565b60055550565b73ffffffffffffffffffffffffffffffffffffffff811615613262576000614bfe826109d6565b905060005b8151811015614c6257818181518110614c1e57614c1e61512e565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff851660009081526018835260408082208583529093529190912055600101614c03565b5060005b8151811015611f455760168181548110614c8257614c8261512e565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff86168352601782526040808420858552909252912055600101614c66565b803573ffffffffffffffffffffffffffffffffffffffff811681146126b657600080fd5b600060208284031215614cf957600080fd5b61397d82614cc3565b6020808252825182820181905260009190848201906040850190845b81811015614d3a57835183529284019291840191600101614d1e565b50909695505050505050565b801515811461326257600080fd5b600080600060608486031215614d6957600080fd5b83359250614d7960208501614cc3565b91506040840135614d8981614d46565b809150509250925092565b600060208284031215614da657600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015614d3a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614dc9565b60008060408385031215614e0e57600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614e7e5781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614e3a565b5091979650505050505050565b60008060408385031215614e9e57600080fd5b614ea783614cc3565b9150614eb560208401614cc3565b90509250929050565b60008060008060808587031215614ed457600080fd5b8435614edf81614d46565b93506020850135614eef81614d46565b92506040850135614eff81614d46565b91506060850135614f0f81614d46565b939692955090935050565b60005b83811015614f35578181015183820152602001614f1d565b50506000910152565b6020815260008251806020840152614f5d816040850160208701614f1a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614fa257600080fd5b614fab83614cc3565b946020939093013593505050565b60008060408385031215614fcc57600080fd5b614fd583614cc3565b91506020830135614fe581614d46565b809150509250929050565b6000806000806080858703121561500657600080fd5b61500f85614cc3565b93506020850135925061502460408601614cc3565b915061503260608601614cc3565b905092959194509250565b60006020828403121561504f57600080fd5b813561397d81614d46565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c0828403121561509b57600080fd5b82601f8301126150aa57600080fd5b60405160c0810181811067ffffffffffffffff821117156150f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c084018581111561510957600080fd5b845b8181101561512357803583526020928301920161510b565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610c7257610c7261515d565b8082028115828204841417610c7257610c7261515d565b6000826151ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610c7257610c7261515d565b60006020828403121561521657600080fd5b5051919050565b600181811c9082168061523157607f821691505b602082108103610b45577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000825161527c818460208701614f1a565b9190910192915050565b60006020828403121561529857600080fd5b815161397d81614d46565b600080604083850312156152b657600080fd5b50508051602090910151909290915056fea2646970667358221220136292d73fa0d5c1542e8129b18b22e0bee7d83eb30bc7f086ae0148341aa9ab64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000be40491f3261fd42724f1aeb465796eb11c06ddf00000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000001af2af8c84000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
-----Decoded View---------------
Arg [0] : _owner (address): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [3] : _rewardRates (uint256[]): 115740740740
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34
Arg [6] : _stakingToken (address): 0xBE40491F3261Fd42724F1AEb465796eb11c06ddF
-----Encoded View---------------
17 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [6] : 000000000000000000000000be40491f3261fd42724f1aeb465796eb11c06ddf
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [10] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [12] : 0000000000000000000000000000000000000000000000000000001af2af8c84
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Deployed Bytecode Sourcemap
102872:4823:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44785:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97796:316;;;;;;:::i;:::-;;:::i;:::-;;;1700:25:1;;;1688:2;1673:18;97796:316:0;1554:177:1;47683:222:0;;;;;;:::i;:::-;;:::i;42787:109::-;;;:::i;:::-;;;;;;;:::i;27668:141::-;;;;;;:::i;:::-;;:::i;:::-;;95360:190;;;;;;:::i;:::-;;:::i;45493:339::-;;;:::i;89127:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;48515:179::-;;;;;;:::i;:::-;;:::i;42199:459::-;;;;;;:::i;:::-;;:::i;:::-;;;4488:14:1;;4481:22;4463:41;;4451:2;4436:18;42199:459:0;4323:187:1;38645:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4691:42:1;4679:55;;;4661:74;;4649:2;4634:18;38645:60:0;4515:226:1;51042:1752:0;;;;;;:::i;:::-;;:::i;68050:572::-;;;;;;:::i;:::-;;:::i;46894:127::-;;;;;;:::i;:::-;46987:26;;46960:7;46987:26;;;:17;:26;;;;;;;46894:127;37481:48;;37523:6;37481:48;;57703:309;;;;;;:::i;:::-;;:::i;37070:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;103338:46;;;:::i;:::-;;;;;;;:::i;49677:181::-;;;;;;:::i;:::-;;:::i;27436:29::-;;;;;;;;;39478:31;;;:::i;105893:1799::-;;;:::i;46502:111::-;46583:22;;46502:111;;37391:55;;;;;;:::i;:::-;;;;;;;;;;;;;;37873:54;;;;;;:::i;:::-;;;;;;;;;;;;;;36273:32;;;;;;43792:681;;;:::i;78245:31::-;;;;;;;;;;;;84318:2692;;;;;;:::i;:::-;;:::i;58960:206::-;;;;;;:::i;:::-;;:::i;78687:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;7201:25:1;;;7257:2;7242:18;;7235:34;;;;7285:18;;;7278:34;;;;7343:2;7328:18;;7321:34;7386:3;7371:19;;7364:35;7188:3;7173:19;78687:53:0;6942:463:1;27817:271:0;;;:::i;38440:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;50054:199;;;;;;:::i;:::-;;:::i;69418:1099::-;;;;;;:::i;:::-;;:::i;39418:34::-;;;;;;;;;;;;87071:1961;;;;;;:::i;:::-;;:::i;:::-;;;;7612:25:1;;;7668:2;7653:18;;7646:34;;;;7696:18;;;7689:34;7600:2;7585:18;87071:1961:0;7410:319:1;27409:20:0;;;;;;;;;69022:161;;;;;;:::i;:::-;;:::i;38767:26::-;;;;;;;;;48971:224;;;;;;:::i;:::-;;:::i;36394:55::-;;;;;;91968:1555;;;;;;:::i;:::-;;:::i;36118:62::-;;;;;;58498:172;;;;;;:::i;:::-;;:::i;50406:444::-;;;;;;:::i;:::-;;:::i;35964:29::-;;;;;;89336:133;;;;;;:::i;:::-;89433:21;;89406:7;89433:21;;;:12;:21;;;;;:28;;89336:133;36044:50;;;;;;35637:30;;;;;;93577:1648;;;;;;:::i;:::-;;:::i;48140:166::-;;;;;;:::i;:::-;;:::i;72492:483::-;;;;;;:::i;:::-;;:::i;53814:800::-;;;;;;:::i;:::-;;:::i;46260:128::-;;;;;;:::i;:::-;46354:26;;46327:7;46354:26;;;:17;:26;;;;;;;46260:128;73295:207;;;;;;:::i;:::-;;:::i;45995:113::-;46077:23;;45995:113;;68786:97;;;:::i;53048:610::-;;;;;;:::i;:::-;;:::i;35857:27::-;;;;;;36532:51;;;;;;36608:59;;;;;;43270:452;;;;;;:::i;:::-;;:::i;66111:761::-;;;;;;:::i;:::-;;:::i;70980:958::-;;;;;;:::i;:::-;;:::i;66971:482::-;;;:::i;44785:529::-;44839:27;44879;44909:17;:15;:17::i;:::-;44964:12;:19;44879:47;;-1:-1:-1;44950:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44950:34:0;-1:-1:-1;45001:26:0;;;45030:1;45001:26;;;:17;:26;;;;;;44937:47;;-1:-1:-1;45001:30:0;44997:310;;45052:9;45047:249;45071:12;:19;45067:23;;45047:249;;;45261:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;45180:32;;;:23;:32;;;;;:35;;;;;;;;;45164:13;;45220:4;;45180:35;45164:10;;45278:1;;45164:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;45134:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;45133:91;;;;:::i;:::-;45132:148;;;;:::i;:::-;45116:10;45127:1;45116:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;45092:3;;45047:249;;;;44997:310;44868:446;44785:529;;;:::o;97796:316::-;97927:7;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;;;;;;;;;31685:1;32424:18;;97955:17:::1;::::0;::::1;::::0;::::1;;;:26;97947:57;;;::::0;::::1;::::0;;11405:2:1;97947:57:0::1;::::0;::::1;11387:21:1::0;11444:2;11424:18;;;11417:30;11483:20;11463:18;;;11456:48;11521:18;;97947:57:0::1;11203:342:1::0;97947:57:0::1;98022:82;98038:10;98050:19;98071:6;98079:24;98022:15;:82::i;:::-;31641:1:::0;32603:7;:22;98015:89;97796:316;-1:-1:-1;;;;97796:316:0:o;47683:222::-;47792:19;;47857:28;;47742:7;;47769:127;;47827:26;47792:19;47827:4;:26;:::i;:::-;47826:59;;;;:::i;:::-;47769:8;:127::i;:::-;47762:134;47683:222;-1:-1:-1;;47683:222:0:o;42787:109::-;42840:16;42876:12;42869:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42787:109;:::o;27668:141::-;28148:5;;;;28134:10;:19;28126:79;;;;;;;11752:2:1;28126:79:0;;;11734:21:1;11791:2;11771:18;;;11764:30;11830:34;11810:18;;;11803:62;11901:17;11881:18;;;11874:45;11936:19;;28126:79:0;11550:411:1;28126:79:0;27740:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;27779:22:::1;::::0;4661:74:1;;;27779:22:0::1;::::0;4649:2:1;4634:18;27779:22:0::1;;;;;;;27668:141:::0;:::o;95360:190::-;95445:7;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;95472:70:::1;95485:10;::::0;95509:9;95520:4;95526:15:::1;95472:12;:70::i;:::-;31641:1:::0;32603:7;:22;95465:77;95360:190;-1:-1:-1;;;95360:190:0:o;45493:339::-;45643:17;:24;45548:41;;45629:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45629:39:0;;45602:66;;45686:9;45681:144;45705:17;:24;45701:28;;45681:144;;;37523:6;45781:14;45793:1;45781:11;:14::i;:::-;:32;;;;:::i;:::-;45751:24;45776:1;45751:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;45731:3;;45681:144;;;;45493:339;:::o;89127:133::-;89231:21;;;;;;;:12;:21;;;;;;;;89224:28;;;;;;;;;;;;;;;;;89191:20;;89224:28;;89231:21;;89224:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89127:133;;;:::o;48515:179::-;48630:32;;;48584:7;48630:32;;;:17;:32;;;;;;48612:15;;35765:4;;48612:50;;;:::i;:::-;48611:75;;;;:::i;42199:459::-;42316:32;;;42295:4;42316:32;;;:13;:32;;;;;;;;42311:297;;-1:-1:-1;42357:5:0;42350:12;;42311:297;42382:25;;;;;:60;;-1:-1:-1;42411:31:0;;;;42382:60;42378:230;;;-1:-1:-1;42451:5:0;42444:12;;42378:230;42491:5;;;;;;42476:20;;;;42472:136;;-1:-1:-1;42505:4:0;42498:11;;42472:136;42547:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;42543:65;;-1:-1:-1;42604:4:0;42597:11;;42543:65;-1:-1:-1;42644:5:0;42199:459;;;;:::o;51042:1752::-;51105:24;;;51266:20;51278:7;51266:11;:20::i;:::-;51246:40;-1:-1:-1;51317:23:0;;;;51316:81;;51371:26;;;;;4691:42:1;4679:55;;51371:26:0;;;4661:74:1;35372:42:0;;51371:15;;4634:18:1;;51371:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51316:81;;;51344:24;;;;;4691:42:1;4679:55;;51344:24:0;;;4661:74:1;35372:42:0;;51344:15;;4634:18:1;;51344:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51297:100;;51503:19;35765:4;35372:42;51627:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;51568:24;;51545:20;;51526:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;51525:145;;;;:::i;:::-;51503:167;-1:-1:-1;51779:19:0;;51994:23;;;;51993:94;;52052:35;52077:9;52052:24;:35::i;:::-;51993:94;;;52021:28;52041:7;52021:19;:28::i;:::-;51964:123;-1:-1:-1;52108:30:0;;52104:323;;52159:27;52233:26;52190:39;35765:4;52190:16;:39;:::i;:::-;52189:70;;;;:::i;:::-;52159:100;;35765:4;52333:20;;52311:19;:42;;;;:::i;:::-;52310:67;;;;:::i;:::-;52296:81;;52139:254;52104:323;;;52426:1;52412:15;;52104:323;51809:699;52595:11;52581;:25;:53;;52623:11;52581:53;;;52609:11;52581:53;52561:74;;52725:20;;52706:16;:39;52702:84;;;52766:20;;52747:39;;52702:84;51131:1663;;;;51042:1752;;;:::o;68050:572::-;39688:5;;;;39674:10;:19;;:79;;-1:-1:-1;39711:42:0;39697:10;:56;39674:79;39666:113;;;;;;;12357:2:1;39666:113:0;;;12339:21:1;12396:2;12376:18;;;12369:30;12435:23;12415:18;;;12408:51;12476:18;;39666:113:0;12155:345:1;39666:113:0;68252:13:::1;:30:::0;;68293:38;;68252:30;;::::1;;;68293:38:::0;;;68252:30:::1;68293:38:::0;::::1;;;;68342:50:::0;::::1;::::0;;::::1;;;;::::0;;68533:23;:50;::::1;;;-1:-1:-1::0;68561:22:0::1;::::0;;;::::1;;;68560:23;68533:50;68530:84;;;68585:22;:29:::0;;;::::1;::::0;::::1;::::0;;68530:84:::1;68050:572:::0;;;;:::o;57703:309::-;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;57801:22:::1;::::0;;;::::1;;;57800:23;57792:60;;;::::0;::::1;::::0;;12707:2:1;57792:60:0::1;::::0;::::1;12689:21:1::0;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;57792:60:0::1;12505:348:1::0;57792:60:0::1;57871:23;::::0;;;::::1;;;:32;57863:70;;;::::0;::::1;::::0;;13060:2:1;57863:70:0::1;::::0;::::1;13042:21:1::0;13099:2;13079:18;;;13072:30;13138:27;13118:18;;;13111:55;13183:18;;57863:70:0::1;12858:349:1::0;57863:70:0::1;-1:-1:-1::0;31641:1:0;32603:7;:22;57703:309::o;103338:46::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;49677:181::-;49744:7;35765:4;49798:28;;49772:23;49787:7;49772:14;:23::i;:::-;:54;;;;:::i;39478:31::-;;;;;;;:::i;105893:1799::-;107637:12;;;:34;;;;;107666:4;107637:34;;;1700:25:1;105949::0;;107637:12;;;;;;;:28;;1673:18:1;107637:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;107617:54;;105893:1799;:::o;43792:681::-;43840:41;43898:23;;43925:1;43898:28;:59;;;-1:-1:-1;43930:22:0;;:27;43898:59;43894:572;;;43981:21;43974:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43792:681;:::o;43894:572::-;44085:12;:19;44071:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44071:34:0;;44044:61;;44125:9;44120:289;44144:21;:28;44140:32;;44120:289;;;44352:22;;44327:14;44339:1;44327:11;:14::i;:::-;44309;;44280:26;:24;:26::i;:::-;:43;;;;:::i;:::-;44279:62;;;;:::i;:::-;:69;;44344:4;44279:69;:::i;:::-;44278:96;;;;:::i;:::-;44228:21;44250:1;44228:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;44198:24;44223:1;44198:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;44174:3;;44120:289;;84318:2692;84509:21;;;84407:32;84509:21;;;:12;:21;;;;;:32;;84407;;84509:21;84531:9;;84509:32;;;;;;:::i;:::-;;;;;;;;;84478:63;;;;;;;;84509:32;;;;;;;84478:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84724:28;;;;;:19;:28;;;;;;84478:63;;-1:-1:-1;;84720:224:0;;;-1:-1:-1;84817:25:0;;;;84720:224;;;-1:-1:-1;84904:28:0;;;;;;;:19;:28;;;;;;84720:224;85033:15;85003:9;:26;;;:45;84999:1802;;85228:26;;;;85197:28;;;;;;;:19;:28;;;;;;:57;85193:1087;;;85274:26;85332:17;85303:9;:26;;;:46;;;;:::i;:::-;85274:75;;85368:25;85414:9;:26;;;85396:15;:44;;;;:::i;:::-;85368:72;-1:-1:-1;85520:33:0;85556:38;85571:22;85592:1;85571:18;:22;:::i;85556:38::-;85520:74;-1:-1:-1;85811:17:0;85883:21;85887:17;85811;85883:21;:::i;:::-;85832:46;85860:18;85832:25;:46;:::i;:::-;85831:74;;;;:::i;:::-;85811:94;-1:-1:-1;85964:38:0;85985:17;85964:18;:38;:::i;:::-;85951:52;;:9;:52;:::i;:::-;85924:79;;85255:764;;;;84999:1802;;85193:1087;86263:1;86236:28;;84999:1802;;;86425:21;86480:20;86532:17;86503:9;:26;;;:46;;;;:::i;:::-;86480:69;;86568:20;86620:15;86591:9;:26;;;:44;;;;:::i;:::-;86568:67;-1:-1:-1;86702:1:0;86671:27;86568:67;86671:12;:27;:::i;:::-;86670:33;;;;:::i;:::-;86654:49;;86461:258;;86760:29;86775:13;86760:14;:29::i;:::-;86733:56;;86345:456;84999:1802;86923:9;:25;;;86896:24;:52;86892:110;;;86977:9;:25;;;86950:52;;86892:110;84441:2569;;84318:2692;;;;:::o;58960:206::-;59062:16;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;59098:60:::1;59109:10;59121:19:::0;59142:15;59098:10:::1;:60::i;78687:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78687:53:0;;-1:-1:-1;78687:53:0;;;:::o;27817:271::-;27886:14;;;;27872:10;:28;27864:94;;;;;;;14064:2:1;27864:94:0;;;14046:21:1;14103:2;14083:18;;;14076:30;14142:34;14122:18;;;14115:62;14213:23;14193:18;;;14186:51;14254:19;;27864:94:0;13862:417:1;27864:94:0;27987:5;;;27994:14;27974:35;;;27987:5;;;;14519:34:1;;27994:14:0;;;;14584:2:1;14569:18;;14562:43;27974:35:0;;14431:18:1;27974:35:0;;;;;;;28028:14;;;;28020:22;;;;;;28028:14;;;28020:22;;;;28053:27;;;27817:271::o;50054:199::-;50132:7;35765:4;50193:28;;50160:30;50176:13;50160:15;:30::i;69418:1099::-;39891:5;;69504:12;;39891:5;;39877:10;:19;;:74;;;39900:51;39918:10;39930:20;39900:17;:51::i;:::-;39869:107;;;;;;;14818:2:1;39869:107:0;;;14800:21:1;14857:2;14837:18;;;14830:30;14896:22;14876:18;;;14869:50;14936:18;;39869:107:0;14616:344:1;39869:107:0;69602:27:::1;::::0;::::1;69586:13;69602:27:::0;;;:13:::1;:27;::::0;;;;;::::1;;::::0;69856:54;::::1;;;-1:-1:-1::0;69868:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;69900:10;69868:42;69856:54;69855:113;;;;69934:8;69933:9;:34;;;;-1:-1:-1::0;69961:5:0::1;::::0;::::1;;69947:10;:19;69933:34;69833:677;;;70280:66;70308:12;70322:10;70334:11;70280:27;:66::i;69833:677::-;70462:36;::::0;::::1;::::0;;15167:2:1;70462:36:0::1;::::0;::::1;15149:21:1::0;15206:2;15186:18;;;15179:30;15245:28;15225:18;;;15218:56;15291:18;;70462:36:0::1;14965:350:1::0;39987:1:0::1;69418:1099:::0;;;:::o;87071:1961::-;87374:26;;;87172:27;87374:26;;;:17;:26;;;;;;;87172:27;87561:24;87392:7;87561:15;:24::i;:::-;87661:26;;;87598:33;87661:26;;;:17;:26;;;;;;87538:47;;-1:-1:-1;87598:33:0;87661:31;:66;;;;-1:-1:-1;87696:26:0;;;;;;;:17;:26;;;;;;:31;87661:66;87660:143;;;-1:-1:-1;87771:31:0;;;;;;;:22;:31;;;;;;87747:55;;;87660:143;87642:638;;;-1:-1:-1;88044:20:0;87642:638;;;88232:31;;;;;;;:22;:31;;;;;;88267:1;;88209:54;;:20;:54;:::i;:::-;88208:60;;;;:::i;:::-;88180:88;;87642:638;88415:1;88393:23;;88432:9;88427:598;88451:21;;;;;;;:12;:21;;;;;:28;88447:32;;88427:598;;;88532:21;;;88501:28;88532:21;;;:12;:21;;;;;:24;;88554:1;;88532:24;;;;;;:::i;:::-;;;;;;;;;;;88501:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88628:32;88663:34;88686:7;88695:1;88663:22;:34::i;:::-;88779:19;;;;88628:69;;-1:-1:-1;88759:17:0;35765:4;88874:52;88901:25;88628:69;88874:52;:::i;:::-;88861:66;;:9;:66;:::i;:::-;88860:91;;;;:::i;:::-;88847:105;;:9;:105;:::i;:::-;88813:139;-1:-1:-1;88967:46:0;88813:139;88967:46;;:::i;:::-;;-1:-1:-1;;88481:3:0;;;;;-1:-1:-1;88427:598:0;;-1:-1:-1;;88427:598:0;;;87301:1731;87071:1961;;;;;:::o;69022:161::-;39688:5;;;;39674:10;:19;;:79;;-1:-1:-1;39711:42:0;39697:10;:56;39674:79;39666:113;;;;;;;12357:2:1;39666:113:0;;;12339:21:1;12396:2;12376:18;;;12369:30;12435:23;12415:18;;;12408:51;12476:18;;39666:113:0;12155:345:1;39666:113:0;69143:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;69107:68;;::::1;69143:32;::::0;;::::1;69142:33;69107:68;::::0;;69022:161::o;48971:224::-;49037:7;49171:15;;49140:28;;:46;;;;:::i;:::-;49065:24;;;;;4691:42:1;4679:55;;49065:24:0;;;4661:74:1;35765:4:0;;;;35372:42;;49065:15;;4634:18:1;;49065:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;91968:1555::-;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;92109:13:::1;::::0;;;::::1;;;92108:14;92100:41;;;::::0;::::1;::::0;;15522:2:1;92100:41:0::1;::::0;::::1;15504:21:1::0;15561:2;15541:18;;;15534:30;15600:16;15580:18;;;15573:44;15634:18;;92100:41:0::1;15320:338:1::0;92100:41:0::1;92209:22;::::0;;;::::1;;;92208:23;92200:60;;;::::0;::::1;::::0;;12707:2:1;92200:60:0::1;::::0;::::1;12689:21:1::0;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;92200:60:0::1;12505:348:1::0;92200:60:0::1;92324:40;92335:10;92347;92359:4;92324:10;:40::i;:::-;;92426:28;92456:21:::0;92481:29:::1;92491:10;92503:6;92481:9;:29::i;:::-;92425:85;;;;92560:15;92600:8;92578:9;:19;;;:30;;;;:::i;:::-;92560:48:::0;-1:-1:-1;92779:12:0::1;::::0;92739:91:::1;::::0;92779:12:::1;::::0;::::1;;;92794:10;92814:4;92821:8:::0;92739:31:::1;:91::i;:::-;93179:186;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;93226:25:::0;;::::1;::::0;93179:186;;::::1;::::0;;;;;;;;93288:26;;::::1;::::0;93179:186;;;;;93329:25;;::::1;::::0;93179:186;;;;93150:10:::1;-1:-1:-1::0;93137:24:0;;;:12:::1;:24:::0;;;;;;;:39;;93162:13;;93137:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93409:42;93424:10;93436:8;93446:4;93409:14;:42::i;:::-;93469:46;::::0;;16182:25:1;;;16238:2;16223:18;;16216:34;;;93486:10:0::1;::::0;93469:46:::1;::::0;16155:18:1;93469:46:0::1;;;;;;;-1:-1:-1::0;;31641:1:0;32603:7;:22;-1:-1:-1;;;91968:1555:0:o;58498:172::-;58577:16;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;58613:49:::1;58624:10;58636:19:::0;58657:4:::1;58613:10;:49::i;:::-;31641:1:::0;32603:7;:22;58606:56;58498:172;-1:-1:-1;;58498:172:0:o;50406:444::-;50485:25;;;50462:7;50485:25;;;:19;:25;;;;;;;;50481:362;;;-1:-1:-1;50688:4:0;50406:444::o;50481:362::-;-1:-1:-1;50800:31:0;;;;;;;;:25;:31;;;;;;;;50406:444::o;50481:362::-;50406:444;;;:::o;93577:1648::-;31685:1;32291:7;;:19;32283:63;;;;;;;11045:2:1;32283:63:0;;;11027:21:1;11084:2;11064:18;;;11057:30;11123:33;11103:18;;;11096:61;11174:18;;32283:63:0;10843:355:1;32283:63:0;31685:1;32424:18;;93719:13:::1;::::0;;;::::1;;;93718:14;93710:41;;;::::0;::::1;::::0;;15522:2:1;93710:41:0::1;::::0;::::1;15504:21:1::0;15561:2;15541:18;;;15534:30;15600:16;15580:18;;;15573:44;15634:18;;93710:41:0::1;15320:338:1::0;93710:41:0::1;93819:22;::::0;;;::::1;;;93818:23;93810:60;;;::::0;::::1;::::0;;12707:2:1;93810:60:0::1;::::0;::::1;12689:21:1::0;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;93810:60:0::1;12505:348:1::0;93810:60:0::1;93934:40;93945:10;93957;93969:4;93934:10;:40::i;:::-;;94036:28;94066:21:::0;94091:29:::1;94101:10;94113:6;94091:9;:29::i;:::-;94035:85;;;;94175:15;94159:13;:31;94151:65;;;::::0;::::1;::::0;;16463:2:1;94151:65:0::1;::::0;::::1;16445:21:1::0;16502:2;16482:18;;;16475:30;16541:23;16521:18;;;16514:51;16582:18;;94151:65:0::1;16261:345:1::0;94151:65:0::1;94262:17;94312:15;94283:9;:26;;;:44;94282:97;;94378:1;94282:97;;;94360:15;94331:9;:26;;;:44;;;;:::i;:::-;94262:117:::0;-1:-1:-1;94390:16:0::1;94409:31;94425:15;94409:13:::0;:31:::1;:::i;:::-;94390:50;;94546:9;94535:8;:20;94527:57;;;::::0;::::1;::::0;;16813:2:1;94527:57:0::1;::::0;::::1;16795:21:1::0;16852:2;16832:18;;;16825:30;16891:26;16871:18;;;16864:54;16935:18;;94527:57:0::1;16611:348:1::0;94527:57:0::1;94615:13;;94603:8;:25;;94595:64;;;::::0;::::1;::::0;;17166:2:1;94595:64:0::1;::::0;::::1;17148:21:1::0;17205:2;17185:18;;;17178:30;17244:28;17224:18;;;17217:56;17290:18;;94595:64:0::1;16964:350:1::0;94595:64:0::1;94690:28;;94678:8;:40;;94670:80;;;::::0;::::1;::::0;;17521:2:1;94670:80:0::1;::::0;::::1;17503:21:1::0;17560:2;17540:18;;;17533:30;17599:29;17579:18;;;17572:57;17646:18;;94670:80:0::1;17319:351:1::0;94670:80:0::1;94834:174;;;;;;;;94860:6;94834:174;;;;94881:15;94834:174;;;;94911:9;:19;;;94834:174;;;;94945:13;94834:174;;;;94973:24;94988:8;94973:14;:24::i;:::-;94834:174:::0;;94805:10:::1;94792:24;::::0;;;:12:::1;:24;::::0;;;;:39;;94817:13;;94792:39;::::1;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95077:48;95101:10;95113:5;95120:4;95077:23;:48::i;:::-;95143:74;::::0;;17906:25:1;;;17962:2;17947:18;;17940:34;;;95186:15:0::1;17990:18:1::0;;;17983:34;18048:2;18033:18;;18026:34;;;95143:74:0;;95156:10:::1;::::0;95143:74:::1;::::0;;;;;17893:3:1;95143:74:0;;::::1;-1:-1:-1::0;;31641:1:0;32603:7;:22;-1:-1:-1;;;;93577:1648:0:o;48140:166::-;48248:26;;;48202:7;48248:26;;;:17;:26;;;;;;48230:15;;35765:4;;48230:44;;;:::i;72492:483::-;39891:5;;72658:20;;39891:5;;39877:10;:19;;:74;;;39900:51;39918:10;39930:20;39900:17;:51::i;:::-;39869:107;;;;;;;14818:2:1;39869:107:0;;;14800:21:1;14857:2;14837:18;;;14830:30;14896:22;14876:18;;;14869:50;14936:18;;39869:107:0;14616:344:1;39869:107:0;72709:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;72691:17:::1;:61:::0;;72755:9;;72709:42;72691:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;72838:25;72775:16;72792:20;:42;72813:20;72792:42;;;;;;;;;;;;;;;;72775:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;72893:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;72874:18:::1;:62:::0;;72939:28;;72893:42;72874:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;72492:483:::0;;;;;:::o;53814:800::-;53894:34;;;;;;;:19;:34;;;;;;;;53886:60;;;;;;;18273:2:1;53886:60:0;;;18255:21:1;18312:2;18292:18;;;18285:30;18351:15;18331:18;;;18324:43;18384:18;;53886:60:0;18071:337:1;53886:60:0;53965:36;;;;;;;:21;:36;;;;;;;;54002:10;53965:48;;;;;;;;;;53957:90;;;;;;;18615:2:1;53957:90:0;;;18597:21:1;18654:2;18634:18;;;18627:30;18693:31;18673:18;;;18666:59;18742:18;;53957:90:0;18413:353:1;53957:90:0;54193:10;54142:22;54167:37;;;:25;:37;;;;;;;;54219:28;;54215:182;;54374:10;54356:29;;;;:17;:29;;;;;;;;;;54319:33;;;;;;;;;:66;;54356:29;;54319:33;;:66;;54356:29;;54319:66;:::i;:::-;;;;-1:-1:-1;;54215:182:0;54465:10;54439:37;;;;:25;:37;;;;;;;;:53;;;;:37;:53;;;;;;;;54577:17;:29;;;;;;54541:32;;;;;;;;:65;;54577:29;;54541:32;;:65;;54577:29;;54541:65;:::i;:::-;;;;-1:-1:-1;;;;53814:800:0:o;73295:207::-;39891:5;;73403:20;;39891:5;;39877:10;:19;;:74;;;39900:51;39918:10;39930:20;39900:17;:51::i;:::-;39869:107;;;;;;;14818:2:1;39869:107:0;;;14800:21:1;14857:2;14837:18;;;14830:30;14896:22;14876:18;;;14869:50;14936:18;;39869:107:0;14616:344:1;39869:107:0;-1:-1:-1;73436:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;73295:207::o;68786:97::-;39688:5;;;;39674:10;:19;;:79;;-1:-1:-1;39711:42:0;39697:10;:56;39674:79;39666:113;;;;;;;12357:2:1;39666:113:0;;;12339:21:1;12396:2;12376:18;;;12369:30;12435:23;12415:18;;;12408:51;12476:18;;39666:113:0;12155:345:1;39666:113:0;68861:14:::1;::::0;;68843:32;;::::1;68861:14;::::0;;::::1;68860:15;68843:32;::::0;;68786:97::o;53048:610::-;53147:10;53127:31;;;;:19;:31;;;;;;;;53119:57;;;;;;;18273:2:1;53119:57:0;;;18255:21:1;18312:2;18292:18;;;18285:30;18351:15;18331:18;;;18324:43;18384:18;;53119:57:0;18071:337:1;53119:57:0;53262:10;53240:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;53239:50;53187:102;;;;;;;53392:25;:41;;;;;;;;:55;53388:263;;53463:41;;;53515:1;53463:41;;;:25;:41;;;;;;;;:54;;;;;;53606:17;:33;;;;;;53591:10;53573:29;;;;;;;:66;;53606:33;;53573:29;;:66;;53606:33;;53573:66;:::i;:::-;;;;-1:-1:-1;;53388:263:0;53048:610;:::o;43270:452::-;43331:16;43360:32;43395:16;43412:9;43395:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;43437:38:0;;43433:282;;43618:4;43576:27;43604:9;43576:38;;;;;;;;:::i;:::-;;;;;;;;;43525:24;43504:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;43503:119;;;;:::i;:::-;43492:130;;43433:282;;;43675:17;43693:9;43675:28;;;;;;;;:::i;:::-;;;;;;;;;43664:39;;43349:373;43270:452;;;:::o;66111:761::-;66228:9;66223:642;66247:16;:23;66243:27;;66223:642;;;66292:32;66327:16;66344:1;66327:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;66365:38:0;;66361:493;;66428:12;:61;;;;66463:22;66486:1;66463:25;;;;;;;;:::i;:::-;;;;;;;;;66445:15;:43;66428:61;66424:415;;;66603:106;;;;;66686:4;66603:106;;;18945:74:1;66693:15:0;19035:18:1;;;19028:34;66603:74:0;;;;;;18918:18:1;;66603:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66570:27;66598:1;66570:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;66781:24;66760:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66732:22;66755:1;66732:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;66424:415;-1:-1:-1;66272:3:0;;66223:642;;;;66111:761;:::o;70980:958::-;39688:5;;;;39674:10;:19;;:79;;-1:-1:-1;39711:42:0;39697:10;:56;39674:79;39666:113;;;;;;;12357:2:1;39666:113:0;;;12339:21:1;12396:2;12376:18;;;12369:30;12435:23;12415:18;;;12408:51;12476:18;;39666:113:0;12155:345:1;39666:113:0;71389:13;;35765:4:::1;-1:-1:-1::0;71389:37:0::1;71381:69;;;::::0;::::1;::::0;;19275:2:1;71381:69:0::1;::::0;::::1;19257:21:1::0;19314:2;19294:18;;;19287:30;19353:21;19333:18;;;19326:49;19392:18;;71381:69:0::1;19073:343:1::0;71381:69:0::1;71574:13:::0;;::::1;::::0;71591:1:::1;-1:-1:-1::0;71574:18:0;::::1;::::0;71573:44:::1;;-1:-1:-1::0;71598:13:0;;::::1;::::0;71615:1:::1;-1:-1:-1::0;71598:18:0::1;71573:44;71565:69;;;::::0;::::1;::::0;;19964:2:1;71565:69:0::1;::::0;::::1;19946:21:1::0;20003:2;19983:18;;;19976:30;20042:14;20022:18;;;20015:42;20074:18;;71565:69:0::1;19762:336:1::0;71565:69:0::1;71669:13:::0;;71647:19:::1;:35:::0;71669:13:::1;71716::::0;::::1;::::0;71693:20:::1;:36:::0;71771:13;;::::1;::::0;71740:28:::1;:44:::0;71822:13;;::::1;::::0;71795:24:::1;:40:::0;71877:13;;::::1;::::0;71846:28:::1;:44:::0;71917:13;::::1;::::0;71901::::1;:29:::0;70980:958::o;66971:482::-;67060:22;;;;;;;67059:23;67051:60;;;;;;;12707:2:1;67051:60:0;;;12689:21:1;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;67051:60:0;12505:348:1;67051:60:0;67173:25;67192:5;67173:18;:25::i;:::-;67268:16;:14;:16::i;:::-;67250:15;:34;67320:12;;67301:15;:31;67297:149;;67349:14;:12;:14::i;:::-;66971:482::o;67297:149::-;67405:29;:27;:29::i;98623:1792::-;99085:22;;98809:7;;99085:22;;;;;99081:194;;99210:53;99221:14;99237:19;99258:4;99210:10;:53::i;:::-;;99081:194;99328:28;99358:21;99383:33;99393:14;99409:6;99383:9;:33::i;:::-;99327:89;;;;99454:9;:26;;;99435:15;:45;;:71;;;-1:-1:-1;99484:14:0;;;;:22;;:14;:22;99435:71;99427:106;;;;;;;20305:2:1;99427:106:0;;;20287:21:1;20344:2;20324:18;;;20317:30;20383:24;20363:18;;;20356:52;20425:18;;99427:106:0;20103:346:1;99427:106:0;99564:19;;;;99600:13;;99596:783;;100014:12;;99978:82;;100014:12;;;;;100029:19;100050:9;99978:27;:82::i;:::-;100132:28;;;;;;;:12;:28;;;;;:43;;100161:13;;100132:43;;;;;;:::i;:::-;;;;;;;;;;;;;100125:50;;;;;;;;;;;;;;;;;;;;;;;;;;100227:48;;100242:14;;100258:9;;100227:14;:48::i;:::-;100297:70;;;20656:25:1;;;20712:2;20697:18;;20690:34;;;100297:70:0;20760:55:1;;;20740:18;;;20733:83;100297:70:0;;;;;;;;;;;20644:2:1;100297:70:0;;;99596:783;100398:9;98623:1792;-1:-1:-1;;;;;;;98623:1792:0:o;23950:106::-;24008:7;24039:1;24035;:5;:13;;24047:1;24035:13;;;24043:1;24035:13;24028:20;23950:106;-1:-1:-1;;;23950:106:0:o;95746:1688::-;95992:7;95961:14;95977:4;40082:49;40106:7;40115:8;40125:5;40082:23;:49::i;:::-;96021:22:::1;::::0;;;::::1;;;96020:23;96012:60;;;::::0;::::1;::::0;;12707:2:1;96012:60:0::1;::::0;::::1;12689:21:1::0;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;96012:60:0::1;12505:348:1::0;96012:60:0::1;96092:13;::::0;;;::::1;;;96091:14;96083:41;;;::::0;::::1;::::0;;15522:2:1;96083:41:0::1;::::0;::::1;15504:21:1::0;15561:2;15541:18;;;15534:30;15600:16;15580:18;;;15573:44;15634:18;;96083:41:0::1;15320:338:1::0;96083:41:0::1;96151:13;;96143:4;:21;;96135:60;;;::::0;::::1;::::0;;17166:2:1;96135:60:0::1;::::0;::::1;17148:21:1::0;17205:2;17185:18;;;17178:30;17244:28;17224:18;;;17217:56;17290:18;;96135:60:0::1;16964:350:1::0;96135:60:0::1;96222:28;;96214:4;:36;;96206:75;;;::::0;::::1;::::0;;17521:2:1;96206:75:0::1;::::0;::::1;17503:21:1::0;17560:2;17540:18;;;17533:30;17599:29;17579:18;;;17572:57;17646:18;;96206:75:0::1;17319:351:1::0;96206:75:0::1;96404:12;::::0;96364:96:::1;::::0;96404:12:::1;::::0;::::1;;;96419:14:::0;96443:4:::1;96450:9:::0;96364:31:::1;:96::i;:::-;96787:23;96813:20;96828:4;96813:14;:20::i;:::-;96932:33;::::0;::::1;96844:14;96932:33:::0;;;:17:::1;:33;::::0;;;;;;;;96871:95;;21073:66:1;21060:2;21056:15;;;21052:88;96871:95:0;;::::1;21040:101:1::0;;;;21157:12;;;21150:28;;;21194:12;;;21187:28;;;21231:12;;;21224:28;96787:46:0;;-1:-1:-1;96844:14:0;21268:13:1;;96871:95:0::1;::::0;;;;;::::1;::::0;;;;;;96861:106;;96871:95:::1;96861:106:::0;;::::1;::::0;97024:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;97058:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;96861:106;;-1:-1:-1;97024:28:0;97058:164;;;97159:22:::1;97177:4:::0;97105:15;97159:22:::1;:::i;:::-;97058:164:::0;;::::1;::::0;;::::1;::::0;;;97024:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;97024:199:0;;;;;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;97267:47:::1;::::0;97282:14;;97298:9;;97267:14:::1;:47::i;:::-;97332:68;::::0;;21523:25:1;;;21579:2;21564:18;;21557:34;;;21607:18;;;21600:34;;;97332:68:0::1;21670:55:1::0;;;21665:2;21650:18;;21643:83;97332:68:0;::::1;::::0;::::1;::::0;21510:3:1;21495:19;97332:68:0::1;;;;;;;97420:6:::0;95746:1688;-1:-1:-1;;;;;;;;;95746:1688:0:o;42948:133::-;43007:7;43034:39;43043:15;43060:12;;43034:8;:39::i;59262:1313::-;59410:31;59385:8;59395:4;40082:49;40106:7;40115:8;40125:5;40082:23;:49::i;:::-;59509:22:::1;::::0;;;::::1;;;59508:23;59500:60;;;::::0;::::1;::::0;;12707:2:1;59500:60:0::1;::::0;::::1;12689:21:1::0;12746:2;12726:18;;;12719:30;12785:26;12765:18;;;12758:54;12829:18;;59500:60:0::1;12505:348:1::0;59500:60:0::1;59643:23;::::0;;;::::1;;;:32;59635:70;;;::::0;::::1;::::0;;13060:2:1;59635:70:0::1;::::0;::::1;13042:21:1::0;13099:2;13079:18;;;13072:30;13138:27;13118:18;;;13111:55;13183:18;;59635:70:0::1;12858:349:1::0;59635:70:0::1;59804:29;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;59836:15:::1;59804:47:::0;;59963:12:::1;:19:::0;59949:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;59949:34:0::1;;59932:51;;60001:9;59996:419;60020:12;:19:::0;60016:23;::::1;59996:419;;;60081:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;60061:17;;:14;;60099:1;;60061:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;60116:17:::1;::::0;::::1;60139:1;60116:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;60159:17;;:14;;60134:1;;60159:17;::::1;;;;;:::i;:::-;;;;;;;:21;60155:249;;;60201:84;60229:12;60242:1;60229:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;60246:19;60267:14;60282:1;60267:17;;;;;;;;:::i;:::-;;;;;;;60201:27;:84::i;:::-;60322:8;60311:77;;;60332:14;60347:1;60332:17;;;;;;;;:::i;:::-;;;;;;;60351:12;60364:1;60351:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;60311:77:::1;::::0;;21939:25:1;;;60351:15:0::1;::::0;;::::1;22041:18:1::0;;;22034:43;;;;22113:15;;22093:18;;;22086:43;21927:2;21912:18;60311:77:0::1;;;;;;;60155:249;60041:3;;59996:419;;;;59262:1313:::0;;;;;;;:::o;28951:361::-;29146:45;;;29135:10;18963:55:1;;;29146:45:0;;;18945:74:1;19035:18;;;;19028:34;;;29146:45:0;;;;;;;;;;18918:18:1;;;;29146:45:0;;;;;;;;;;;;;29135:57;;-1:-1:-1;;;;29135:10:0;;;;:57;;29146:45;29135:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29099:93;;;;29211:7;:57;;;;-1:-1:-1;29223:11:0;;:16;;:44;;;29254:4;29243:24;;;;;;;;;;;;:::i;:::-;29203:101;;;;;;;22884:2:1;29203:101:0;;;22866:21:1;22923:2;22903:18;;;22896:30;22962:33;22942:18;;;22935:61;23013:18;;29203:101:0;22682:355:1;29203:101:0;29021:291;;28951:361;;;:::o;91315:590::-;91397:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91397:31:0;91430:15;91462:11;;91458:347;;91495:9;91490:304;91514:28;;;;;;;:12;:28;;;;;:35;91510:39;;91490:304;;;91589:28;;;;;;;:12;:28;;;;;:31;;91618:1;;91589:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;91579:6;:48;91575:204;;91666:28;;;;;;;:12;:28;;;;;:31;;91695:1;;91666:31;;;;;;:::i;:::-;;;;;;;;;;;91651:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91730:1;91720:11;;91754:5;;91575:204;91551:3;;91490:304;;;;91458:347;91823:11;;;;;:44;;-1:-1:-1;91838:19:0;;:29;;91823:44;91815:72;;;;;;;23244:2:1;91815:72:0;;;23226:21:1;23283:2;23263:18;;;23256:30;23322:17;23302:18;;;23295:45;23357:18;;91815:72:0;23042:339:1;91815:72:0;91315:590;;;;;:::o;29320:402::-;29545:51;;;29534:10;23667:15:1;;;29545:51:0;;;23649:34:1;23719:15;;;23699:18;;;23692:43;23751:18;;;;23744:34;;;29545:51:0;;;;;;;;;;23561:18:1;;;;29545:51:0;;;;;;;;;;;;;29534:63;;-1:-1:-1;;;;29534:10:0;;;;:63;;29545:51;29534:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29498:99;;;;29616:7;:57;;;;-1:-1:-1;29628:11:0;;:16;;:44;;;29659:4;29648:24;;;;;;;;;;;;:::i;:::-;29608:106;;;;;;;23991:2:1;29608:106:0;;;23973:21:1;24030:2;24010:18;;;24003:30;24069:34;24049:18;;;24042:62;24140:6;24120:18;;;24113:34;24164:19;;29608:106:0;23789:400:1;29608:106:0;29408:314;;29320:402;;;;:::o;90430:877::-;90558:17;90578:27;90590:14;90578:11;:27::i;:::-;90558:47;;90622:6;90618:561;;;90713:3;90686:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;90731:33:0;;;;;;;:17;:33;;;;;:40;;90768:3;;90731:33;:40;;90768:3;;90731:40;:::i;:::-;;;;-1:-1:-1;;90825:23:0;;;;90821:64;;90850:28;;;;;;;:17;:28;;;;;:35;;90882:3;;90850:28;:35;;90882:3;;90850:35;:::i;:::-;;;;-1:-1:-1;;90821:64:0;90618:561;;;90995:3;90968:23;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;91013:33:0;;;;;;;:17;:33;;;;;:40;;91050:3;;91013:33;:40;;91050:3;;91013:40;:::i;:::-;;;;-1:-1:-1;;91107:23:0;;;;91103:64;;91132:28;;;;;;;:17;:28;;;;;:35;;91164:3;;91132:28;:35;;91164:3;;91132:35;:::i;:::-;;;;-1:-1:-1;;91103:64:0;91247:52;91271:14;91287:5;91294:4;54930:1962;55116:22;;;;;;;55111:214;;55264:8;55260:54;;;55292:6;:4;:6::i;:::-;55465:19;55461:109;;;55534:24;55550:7;55534:15;:24::i;:::-;55500:31;;;;;;;:22;:31;;;;;:58;55461:109;55594:21;;;;55590:1295;;55808:27;55854:28;55901:27;55946:30;55968:7;55946:21;:30::i;:::-;56043:22;;55786:190;;-1:-1:-1;55786:190:0;;-1:-1:-1;55786:190:0;-1:-1:-1;56043:22:0;;;;;56038:49;;56067:20;56079:7;56067:11;:20::i;:::-;56163:31;;;;;;;:22;:31;;;;;:54;;;56304:42;;;56300:572;;56367:19;56389:41;56411:19;56389;:41;:::i;:::-;56367:63;;56499:11;56474:22;;:36;;;;:::i;:::-;56449:22;:61;56558:33;56580:11;56558:19;:33;:::i;:::-;56529:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;56300:572:0;;;56632:19;56654:41;56676:19;56654;:41;:::i;:::-;56632:63;;56764:11;56739:22;;:36;;;;:::i;:::-;56714:22;:61;56823:33;56845:11;56823:19;:33;:::i;:::-;56794:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;55617:1268:0;;;54930:1962;;;:::o;60662:4846::-;60749:29;:27;:29::i;:::-;60868:9;60863:327;60887:18;:25;60883:29;;60863:327;;;60934:34;60971:18;60990:1;60971:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;61011:40:0;;61007:172;;61072:91;;;;;61157:4;61072:91;;;4661:74:1;61072:76:0;;;;;;4634:18:1;;61072:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;61007:172;-1:-1:-1;60914:3:0;;60863:327;;;;61550:27;37523:6;61606:12;;61588:15;:30;;;;:::i;:::-;61580:57;;;;:::i;:::-;61550:87;;61776:9;61771:284;61795:12;:19;61791:23;;61771:284;;;61917:12;61930:1;61917:15;;;;;;;;:::i;:::-;;;;;;;;;;;61910:48;;;;;61952:4;61910:48;;;4661:74:1;61917:15:0;;;;;61910:33;;4634:18:1;;61910:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;61881:23;:19;61903:1;61881:23;:::i;:::-;37523:6;61845:14;61857:1;61845:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;61844:114;;62024:12;62037:1;62024:15;;;;;;;;:::i;:::-;;;;;;;;;;;;61967:73;;;24686:34:1;61967:73:0;;;24674:47:1;;;;24751:6;24737:12;;;24730:28;24796:2;24792:15;;;24774:12;;;24767:110;24893:12;;61967:73:0;;;;;;;;;;;;61836:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;61816:3:0;;61771:284;;;-1:-1:-1;37523:6:0;62267:23;:19;62289:1;62267:23;:::i;:::-;62266:43;;;;:::i;:::-;62250:12;;:60;;;;:::i;:::-;62235:12;:75;65471:29;65516:435;65603:34;65640:17;:15;:17::i;:::-;65603:54;;65720:9;65715:133;65739:21;:28;65735:32;;65715:133;;;65816:17;65834:1;65816:20;;;;;;;;:::i;:::-;;;;;;;65789:21;65811:1;65789:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;65769:3;;65715:133;;;;65917:26;:24;:26::i;:::-;65900:14;:43;-1:-1:-1;65516:435:0:o;56900:585::-;56962:21;;;;56958:520;;57039:27;57069:15;57076:7;57069:6;:15::i;:::-;57039:45;;57147:9;57142:118;57166:10;:17;57162:1;:21;57142:118;;;57231:10;57242:1;57231:13;;;;;;;;:::i;:::-;;;;;;;;;;;;57209:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;57185:3;;57142:118;;;;57327:9;57322:145;57346:10;:17;57342:1;:21;57322:145;;;57427:21;57449:1;57427:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;57389:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;57365:3;;57322:145;;14:196:1;82:20;;142:42;131:54;;121:65;;111:93;;200:1;197;190:12;215:186;274:6;327:2;315:9;306:7;302:23;298:32;295:52;;;343:1;340;333:12;295:52;366:29;385:9;366:29;:::i;406:632::-;577:2;629:21;;;699:13;;602:18;;;721:22;;;548:4;;577:2;800:15;;;;774:2;759:18;;;548:4;843:169;857:6;854:1;851:13;843:169;;;918:13;;906:26;;987:15;;;;952:12;;;;879:1;872:9;843:169;;;-1:-1:-1;1029:3:1;;406:632;-1:-1:-1;;;;;;406:632:1:o;1043:118::-;1129:5;1122:13;1115:21;1108:5;1105:32;1095:60;;1151:1;1148;1141:12;1166:383;1240:6;1248;1256;1309:2;1297:9;1288:7;1284:23;1280:32;1277:52;;;1325:1;1322;1315:12;1277:52;1361:9;1348:23;1338:33;;1390:38;1424:2;1413:9;1409:18;1390:38;:::i;:::-;1380:48;;1478:2;1467:9;1463:18;1450:32;1491:28;1513:5;1491:28;:::i;:::-;1538:5;1528:15;;;1166:383;;;;;:::o;1736:180::-;1795:6;1848:2;1836:9;1827:7;1823:23;1819:32;1816:52;;;1864:1;1861;1854:12;1816:52;-1:-1:-1;1887:23:1;;1736:180;-1:-1:-1;1736:180:1:o;1921:681::-;2092:2;2144:21;;;2214:13;;2117:18;;;2236:22;;;2063:4;;2092:2;2315:15;;;;2289:2;2274:18;;;2063:4;2358:218;2372:6;2369:1;2366:13;2358:218;;;2437:13;;2452:42;2433:62;2421:75;;2551:15;;;;2516:12;;;;2394:1;2387:9;2358:218;;2607:248;2675:6;2683;2736:2;2724:9;2715:7;2711:23;2707:32;2704:52;;;2752:1;2749;2742:12;2704:52;-1:-1:-1;;2775:23:1;;;2845:2;2830:18;;;2817:32;;-1:-1:-1;2607:248:1:o;3042:1011::-;3271:2;3323:21;;;3393:13;;3296:18;;;3415:22;;;3242:4;;3271:2;3456;;3474:18;;;;3515:15;;;3242:4;3558:469;3572:6;3569:1;3566:13;3558:469;;;3631:13;;3669:9;;3657:22;;3719:11;;;3713:18;3699:12;;;3692:40;3772:11;;;3766:18;3752:12;;;3745:40;3808:4;3852:11;;;3846:18;3832:12;;;3825:40;3888:4;3932:11;;;3926:18;3912:12;;;3905:40;3974:4;3965:14;;;;4002:15;;;;3594:1;3587:9;3558:469;;;-1:-1:-1;4044:3:1;;3042:1011;-1:-1:-1;;;;;;;3042:1011:1:o;4058:260::-;4126:6;4134;4187:2;4175:9;4166:7;4162:23;4158:32;4155:52;;;4203:1;4200;4193:12;4155:52;4226:29;4245:9;4226:29;:::i;:::-;4216:39;;4274:38;4308:2;4297:9;4293:18;4274:38;:::i;:::-;4264:48;;4058:260;;;;;:::o;4746:647::-;4820:6;4828;4836;4844;4897:3;4885:9;4876:7;4872:23;4868:33;4865:53;;;4914:1;4911;4904:12;4865:53;4953:9;4940:23;4972:28;4994:5;4972:28;:::i;:::-;5019:5;-1:-1:-1;5076:2:1;5061:18;;5048:32;5089:30;5048:32;5089:30;:::i;:::-;5138:7;-1:-1:-1;5197:2:1;5182:18;;5169:32;5210:30;5169:32;5210:30;:::i;:::-;5259:7;-1:-1:-1;5318:2:1;5303:18;;5290:32;5331:30;5290:32;5331:30;:::i;:::-;4746:647;;;;-1:-1:-1;4746:647:1;;-1:-1:-1;;4746:647:1:o;5398:250::-;5483:1;5493:113;5507:6;5504:1;5501:13;5493:113;;;5583:11;;;5577:18;5564:11;;;5557:39;5529:2;5522:10;5493:113;;;-1:-1:-1;;5640:1:1;5622:16;;5615:27;5398:250::o;5653:455::-;5802:2;5791:9;5784:21;5765:4;5834:6;5828:13;5877:6;5872:2;5861:9;5857:18;5850:34;5893:79;5965:6;5960:2;5949:9;5945:18;5940:2;5932:6;5928:15;5893:79;:::i;:::-;6024:2;6012:15;6029:66;6008:88;5993:104;;;;6099:2;5989:113;;5653:455;-1:-1:-1;;5653:455:1:o;6363:254::-;6431:6;6439;6492:2;6480:9;6471:7;6467:23;6463:32;6460:52;;;6508:1;6505;6498:12;6460:52;6531:29;6550:9;6531:29;:::i;:::-;6521:39;6607:2;6592:18;;;;6579:32;;-1:-1:-1;;;6363:254:1:o;6622:315::-;6687:6;6695;6748:2;6736:9;6727:7;6723:23;6719:32;6716:52;;;6764:1;6761;6754:12;6716:52;6787:29;6806:9;6787:29;:::i;:::-;6777:39;;6866:2;6855:9;6851:18;6838:32;6879:28;6901:5;6879:28;:::i;:::-;6926:5;6916:15;;;6622:315;;;;;:::o;7987:403::-;8073:6;8081;8089;8097;8150:3;8138:9;8129:7;8125:23;8121:33;8118:53;;;8167:1;8164;8157:12;8118:53;8190:29;8209:9;8190:29;:::i;:::-;8180:39;;8266:2;8255:9;8251:18;8238:32;8228:42;;8289:38;8323:2;8312:9;8308:18;8289:38;:::i;:::-;8279:48;;8346:38;8380:2;8369:9;8365:18;8346:38;:::i;:::-;8336:48;;7987:403;;;;;;;:::o;8395:241::-;8451:6;8504:2;8492:9;8483:7;8479:23;8475:32;8472:52;;;8520:1;8517;8510:12;8472:52;8559:9;8546:23;8578:28;8600:5;8578:28;:::i;8641:184::-;8693:77;8690:1;8683:88;8790:4;8787:1;8780:15;8814:4;8811:1;8804:15;8830:915;8912:6;8965:3;8953:9;8944:7;8940:23;8936:33;8933:53;;;8982:1;8979;8972:12;8933:53;9031:7;9024:4;9013:9;9009:20;9005:34;8995:62;;9053:1;9050;9043:12;8995:62;9086:2;9080:9;9128:3;9120:6;9116:16;9198:6;9186:10;9183:22;9162:18;9150:10;9147:34;9144:62;9141:242;;;9239:77;9236:1;9229:88;9340:4;9337:1;9330:15;9368:4;9365:1;9358:15;9141:242;9399:2;9392:22;9434:6;9478:3;9463:19;;9494;;;9491:39;;;9526:1;9523;9516:12;9491:39;9550:9;9568:146;9584:6;9579:3;9576:15;9568:146;;;9652:17;;9640:30;;9699:4;9690:14;;;;9601;9568:146;;;-1:-1:-1;9733:6:1;;8830:915;-1:-1:-1;;;;;8830:915:1:o;9750:184::-;9802:77;9799:1;9792:88;9899:4;9896:1;9889:15;9923:4;9920:1;9913:15;9939:184;9991:77;9988:1;9981:88;10088:4;10085:1;10078:15;10112:4;10109:1;10102:15;10128:128;10195:9;;;10216:11;;;10213:37;;;10230:18;;:::i;10261:168::-;10334:9;;;10365;;10382:15;;;10376:22;;10362:37;10352:71;;10403:18;;:::i;10434:274::-;10474:1;10500;10490:189;;10535:77;10532:1;10525:88;10636:4;10633:1;10626:15;10664:4;10661:1;10654:15;10490:189;-1:-1:-1;10693:9:1;;10434:274::o;10713:125::-;10778:9;;;10799:10;;;10796:36;;;10812:18;;:::i;11966:184::-;12036:6;12089:2;12077:9;12068:7;12064:23;12060:32;12057:52;;;12105:1;12102;12095:12;12057:52;-1:-1:-1;12128:16:1;;11966:184;-1:-1:-1;11966:184:1:o;13212:437::-;13291:1;13287:12;;;;13334;;;13355:61;;13409:4;13401:6;13397:17;13387:27;;13355:61;13462:2;13454:6;13451:14;13431:18;13428:38;13425:218;;13499:77;13496:1;13489:88;13600:4;13597:1;13590:15;13628:4;13625:1;13618:15;22140:287;22269:3;22307:6;22301:13;22323:66;22382:6;22377:3;22370:4;22362:6;22358:17;22323:66;:::i;:::-;22405:16;;;;;22140:287;-1:-1:-1;;22140:287:1:o;22432:245::-;22499:6;22552:2;22540:9;22531:7;22527:23;22523:32;22520:52;;;22568:1;22565;22558:12;22520:52;22600:9;22594:16;22619:28;22641:5;22619:28;:::i;24194:245::-;24273:6;24281;24334:2;24322:9;24313:7;24309:23;24305:32;24302:52;;;24350:1;24347;24340:12;24302:52;-1:-1:-1;;24373:16:1;;24429:2;24414:18;;;24408:25;24373:16;;24408:25;;-1:-1:-1;24194:245:1:o
Swarm Source
ipfs://136292d73fa0d5c1542e8129b18b22e0bee7d83eb30bc7f086ae0148341aa9ab
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2.16 | 5,051.8366 | $10,911.97 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.