Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 20241134 | 92 days ago | IN | 0 ETH | 0.05531004 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PikaStakingPool
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./CorePool.sol"; contract PikaStakingPool is Initializable, UUPSUpgradeable, CorePool { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize( address _poolToken, address _rewardToken, address _poolController, uint256 _weight ) external initializer { __Ownable_init(msg.sender); __Pausable_init(); __UUPSUpgradeable_init(); __CorePool_init( _poolToken, _rewardToken, _poolController, _weight ); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. */ function _authorizeUpgrade( address newImplementation ) internal override onlyOwner {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import {IPikaMoon} from "./interfaces/IPikaMoon.sol"; import {Stake} from "./libraries/Stake.sol"; import {CommonErrors} from "./libraries/Errors.sol"; import {ICorePool} from "./interfaces/ICorePool.sol"; import {IPoolController} from "./interfaces/IPoolController.sol"; contract CorePool is OwnableUpgradeable, PausableUpgradeable, ICorePool, ReentrancyGuardUpgradeable { using Stake for Stake.Data; using Stake for uint256; using SafeERC20 for IPikaMoon; /// @dev Data structure representing token holder. struct User { /// @dev pending rewards rewards to be claimed uint256 pendingRewards; /// @dev Total weight uint256 userTotalWeight; /// @dev Checkpoint variable for rewards calculation uint256 rewardsPerWeightPaid; /// @dev An array of holder's stakes Stake.Data[] stakes; } /// @dev Used to calculate rewards. /// @dev Note: stakes are different in duration and "weight" reflects that. /// @dev updates in the _sync function uint256 public rewardsPerWeight; /// @dev Timestamp of the last rewards distribution event. uint256 public lastRewardsDistribution; /// @dev Link to the pool token instance, for example PIKA or PIKA/USDT pair LP token. address public poolToken; /// @dev Link to the reward token instance, for example PIKA address public rewardToken; /// @dev Link to the pool controller IPoolController instance. address public poolController; /// @dev verifier Address for ECDSA claim verification. address public verifierAddress; /** @notice you can lock your tokens for a period between 1 and 12 months. * This changes your token weight. By increasing the duration of your lock, * you will increase the token weight of the locked tokens. * The maximum weight of a locked token is 2 , * which occurs when you lock for a period of 12 months. * @dev Pool weight, initial values are 200 for PIKA pool and 800 for PIKA/USDT. */ uint256 public weight; /// @dev Used to calculate rewards, keeps track of the tokens weight locked in staking. uint256 public globalStakeWeight; /// @dev total pool token reserve. PIKA or PIKA/USDT pair LP token. uint256 public totalTokenStaked; /// @dev upper Bound percentage for early unstake penalty. uint256 public upperBoundSlash; /// @dev lower Bound percentage for early unstake penalty. uint256 public lowerBoundSlash; uint256 private multiplier; // 1000 = 100% uint32 private constant COOLDOWN_PERIOD = 30 days; /// @dev Token holder storage, maps token holder address to their data record. mapping(address => User) public users; /// @dev mapping to prevent signature replay mapping(bytes32 => bool) public signatureUsed; mapping(address => uint256) public coolOffPeriod; function __CorePool_init( address _poolToken, address _rewardToken, address _poolController, uint256 _weight ) internal onlyInitializing { if (_poolToken == address(0)) { revert CommonErrors.ZeroAddress(); } if (_rewardToken == address(0)) { revert CommonErrors.ZeroAddress(); } if (_poolController == address(0)) { revert CommonErrors.ZeroAddress(); } verifierAddress = owner(); //PIKA or PIKA/USDT pair LP token address. poolToken = _poolToken; //PIKA token address. rewardToken = _rewardToken; /// pool controller IPoolController instance. poolController = _poolController; // init the dependent state variables lastRewardsDistribution = _now256(); // direct staking weight 200 and lp staking 800 weight = _weight; upperBoundSlash = 900; // 90% lowerBoundSlash = 100; // 10% multiplier = 1000; // 100% } /** * @notice Stakes specified value of tokens for the specified value of time, * and pays pending rewards rewards if any. * * @dev Requires value to stake and lock duration to be greater than zero. * * @param _value value of tokens to stake * @param _lockDuration stake duration as unix timestamp */ function stake( uint256 _value, uint256 _lockDuration ) external nonReentrant { // checks if the contract is in a paused state if (paused()) revert CommonErrors.ContractIsPaused(); // validate the _value if (_value == 0) revert CommonErrors.ZeroAmount(); // validate the _lockDuration if ( !(_lockDuration >= Stake.MIN_STAKE_PERIOD && _lockDuration <= Stake.MAX_STAKE_PERIOD) ) { revert CommonErrors.InvalidLockDuration(); } // get a link to user data struct, we will write to it later User storage user = users[msg.sender]; // update user state _updateReward(msg.sender); // calculates until when a stake is going to be locked uint256 lockUntil = _now256() + _lockDuration; // calculate stake weight. same as weight function in stake.sol library uint256 stakeWeight = (((lockUntil - _now256()) * Stake.WEIGHT_MULTIPLIER) / Stake.MAX_STAKE_PERIOD + Stake.BASE_WEIGHT) * _value; // makes sure stakeWeight is valid require(stakeWeight > 0); // create and save the stake (append it to stakes array) Stake.Data memory userStake = Stake.Data({ stakeId: user.stakes.length, value: _value, lockedFrom: _now256(), lockedUntil: lockUntil, isUnstaked: false }); // pushes new stake to `stakes` array user.stakes.push(userStake); // update user weight user.userTotalWeight += stakeWeight; // update global weight value globalStakeWeight += stakeWeight; // update pool reserve totalTokenStaked += _value; // transfer `_value` to this contract IPikaMoon(poolToken).safeTransferFrom( msg.sender, address(this), _value ); // emits an event emit LogStake(msg.sender, (user.stakes.length - 1), _value, lockUntil); } function stakeAsPool( address _staker, uint256 _value ) external nonReentrant { // checks if the contract is in a paused state if (paused()) revert CommonErrors.ContractIsPaused(); IPoolController _controller = IPoolController(poolController); if (!_controller.poolExists(msg.sender)) { revert CommonErrors.UnAuthorized(); } // gets storage pointer to user User storage user = users[_staker]; // update user state _updateReward(_staker); uint256 lockUntil = _now256() + Stake.MAX_STAKE_PERIOD; uint256 stakeWeight = (((lockUntil - _now256()) * Stake.WEIGHT_MULTIPLIER) / Stake.MAX_STAKE_PERIOD + Stake.BASE_WEIGHT) * _value; // initialize new yield stake being created in memory Stake.Data memory newStake = Stake.Data({ stakeId: user.stakes.length, value: _value, lockedFrom: _now256(), lockedUntil: lockUntil, isUnstaked: false }); // sum new yield stake weight to user's total weight user.userTotalWeight += stakeWeight; // add the new yield stake to storage user.stakes.push(newStake); // update global weight and global pool token count globalStakeWeight += stakeWeight; totalTokenStaked += _value; IPoolController(poolController).transferRewardTokens( rewardToken, address(this), _value ); // emits an event emit LogStake(_staker, (user.stakes.length - 1), _value, lockUntil); } /** * @dev Unstakes a stake that has been previously locked, and is now in an unlocked * state if user tries to early unstake he is slashed according to percentage of time calculations * restricted by upper and lower bound * * @param _stakeId stake ID to unstake from, zero-indexed */ function unstake(uint256 _stakeId) external { // checks if the contract is in a paused state if (paused()) revert CommonErrors.ContractIsPaused(); // get a link to user data struct, we will write to it later User storage user = users[msg.sender]; // update user state _updateReward(msg.sender); // get a link to the corresponding stake, we may write to it later Stake.Data storage userStake = user.stakes[_stakeId]; uint256 stakeValue = userStake.value; if (user.stakes[_stakeId].isUnstaked) { revert CommonErrors.AlreadyUnstaked(); } // store stake weight uint256 previousWeight = userStake.weight(); // update user record user.userTotalWeight = user.userTotalWeight - previousWeight; // update global weight variable globalStakeWeight = globalStakeWeight - previousWeight; // update global pool token count totalTokenStaked -= stakeValue; // mark stake struct as unstaked user.stakes[_stakeId].isUnstaked = true; // checks if stake is unlocked already if (_now256() < userStake.lockedUntil) { uint256 earlyUnstakePercentage = calculateEarlyUnstakePercentage( userStake.lockedFrom, _now256(), userStake.lockedUntil ); uint256 unstakeValue = stakeValue - ((stakeValue * earlyUnstakePercentage) / multiplier); // transfer slash amount IPikaMoon(poolToken).safeTransfer( poolController, stakeValue - unstakeValue ); // return user stake IPikaMoon(poolToken).safeTransfer(msg.sender, unstakeValue); // emits an event emit LogUnstake( msg.sender, _stakeId, unstakeValue, earlyUnstakePercentage, true ); } else { // return user stake IPikaMoon(poolToken).safeTransfer(msg.sender, stakeValue); // emits an event emit LogUnstake(msg.sender, _stakeId, stakeValue, 0, false); } } /** * @notice Calculates the penalty percentage for early unstaking based on the remaining locked time * @dev This function returns a penalty percentage scaled by `multiplier`. The function applies bounds to the penalty, ensuring it does not fall below `lowerBoundSlash` or exceed `upperBoundSlash`. * @param lockedFrom The timestamp when the stake was locked * @param nowTime The current timestamp, representing the moment of the unstaking request * @param lockedUntil The timestamp until which the stake was meant to be locked * @return penaltyPercentage The penalty percentage for unstaking early, scaled by `multiplier`. If the stake period has ended, returns 0. */ function calculateEarlyUnstakePercentage( uint256 lockedFrom, uint256 nowTime, uint256 lockedUntil ) public view returns (uint256) { if (nowTime <= lockedUntil) { uint256 percentageToSlash = (((lockedUntil - nowTime)) * multiplier) / (lockedUntil - lockedFrom); if (percentageToSlash < lowerBoundSlash) { return lowerBoundSlash; } else if (percentageToSlash > upperBoundSlash) { return upperBoundSlash; } else { return percentageToSlash; } } else { return 0; } } /** * @dev Prefixes a bytes32 hash with the string "\x19Ethereum Signed Message:\n32" and then hashes the result. * This is used to conform with the Ethereum signing standard (EIP-191). * @param hash The original hash that needs to be prefixed and rehashed. * @return The prefixed and rehashed bytes32 value. */ function prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) ); } /** * @notice Claims a percentage of the accrued rewards for the caller * @dev This function handles the claim process by validating the signature and calculating the reward percentage * @param _claimPercentage The percentage of the pending rewards to claim, scaled by the MULTIPLIER * @param _signature Cryptographic signature to verify the authenticity of the claim * @param nonce A unique identifier to prevent replay attacks */ function claimRewards( uint256 _claimPercentage, bool _restakeLeftOver, bytes calldata _signature, uint256 nonce ) external { // lock duration recommended to be of 1 year to mitigate protocol abuse // checks if the contract is in a paused state if (paused()) revert CommonErrors.ContractIsPaused(); require(_claimPercentage <= multiplier); if (!_restakeLeftOver && _claimPercentage != 0) { if (_now256() < coolOffPeriod[msg.sender] + COOLDOWN_PERIOD) { revert CommonErrors.CoolOffPeriodIsNotOver(); } } coolOffPeriod[msg.sender] = _now256(); // Update the last claim time bytes32 message = prefixed( keccak256( abi.encodePacked( msg.sender, _claimPercentage, _restakeLeftOver, nonce ) ) ); require(!signatureUsed[message]); signatureUsed[message] = true; if (ECDSA.recover(message, _signature) != verifierAddress) { revert CommonErrors.WrongHash(); } // update user state _updateReward(msg.sender); // get link to a user data structure, we will write into it later User storage user = users[msg.sender]; // if pending rewards is zero revert if (user.pendingRewards == 0) return; if (_claimPercentage == 0 && !_restakeLeftOver) { revert CommonErrors.InvalidOperation(); } if (_claimPercentage != 0) { uint256 toClaim = (user.pendingRewards * _claimPercentage) / multiplier; user.pendingRewards -= toClaim; // transfer pending rewards to staker IPoolController(poolController).transferRewardTokens( rewardToken, msg.sender, toClaim ); // emits an event emit LogClaimRewards(msg.sender, toClaim); } if (_restakeLeftOver && _claimPercentage < multiplier) { if (poolToken == rewardToken) { uint256 pendingRewardsToClaim = user.pendingRewards; user.pendingRewards = 0; // calculates until when a stake is going to be locked uint256 lockUntil = _now256() + Stake.MAX_STAKE_PERIOD; // calculate stake weight. same as weight function in stake.sol library uint256 stakeWeight = (((lockUntil - _now256()) * Stake.WEIGHT_MULTIPLIER) / Stake.MAX_STAKE_PERIOD + Stake.BASE_WEIGHT) * pendingRewardsToClaim; // makes sure stakeWeight is valid require(stakeWeight > 0); // create and save the stake (append it to stakes array) Stake.Data memory userStake = Stake.Data({ stakeId: user.stakes.length, value: pendingRewardsToClaim, lockedFrom: _now256(), lockedUntil: lockUntil, isUnstaked: false }); // pushes new stake to `stakes` array user.stakes.push(userStake); // update user weight user.userTotalWeight += stakeWeight; // update global weight value globalStakeWeight += stakeWeight; // update pool reserve totalTokenStaked += pendingRewardsToClaim; IPoolController(poolController).transferRewardTokens( rewardToken, address(this), pendingRewardsToClaim ); // emits an event emit LogStake( msg.sender, (user.stakes.length - 1), pendingRewardsToClaim, lockUntil ); } else { uint256 pendingRewardsToClaim = user.pendingRewards; user.pendingRewards = 0; address poolAddress = IPoolController(poolController).pools(rewardToken); ICorePool(poolAddress) .stakeAsPool(msg.sender, pendingRewardsToClaim); } } } /** * @notice Calculates current rewards rewards value available for address specified. * @param _staker an address to calculate rewards rewards value for */ function pendingRewards( address _staker ) external view returns (uint256 _pendingRewards) { if (_staker == address(0)) revert CommonErrors.ZeroAddress(); // `newrewardsPerWeight` will be the stored or recalculated value for `rewardsPerWeight` uint256 newrewardsPerWeight; // gas savings uint256 _lastRewardsDistribution = lastRewardsDistribution; // based on the rewards per weight value, calculate pending rewards; // storage takes less gas User storage user = users[_staker]; // initializes both variables from one storage slot uint256 userWeight = user.userTotalWeight; // if smart contract state was not updated recently, `rewardsPerWeight` value // is outdated and we need to recalculate it in order to calculate pending rewards correctly if (_now256() > _lastRewardsDistribution && globalStakeWeight != 0) { IPoolController _controller = IPoolController(poolController); uint256 secondsPassed = _now256() - _lastRewardsDistribution; uint256 pikaRewards = (secondsPassed * _controller.pikaPerSecond() * weight) / _controller.totalWeight(); // recalculated value for `rewardsPerWeight` newrewardsPerWeight = pikaRewards.getRewardPerWeight((globalStakeWeight)) + rewardsPerWeight; } else { // if smart contract state is up to date, we don't recalculate newrewardsPerWeight = rewardsPerWeight; } _pendingRewards = (userWeight).earned( newrewardsPerWeight, user.rewardsPerWeightPaid ) + user.pendingRewards; } /** * @dev Must be called every time user.userTotalWeight is changed. * @dev Syncs the global pool state, processes the user pending rewards (if any), * and updates check points values stored in the user struct. * @dev If user is coming from v1 pool, it expects to receive this v1 user weight * to include in rewards calculations. * * @param _staker user address */ function _updateReward(address _staker) internal { // update pool state _sync(); // gets storage reference to the user User storage user = users[_staker]; // gas savings uint256 userTotalWeight = user.userTotalWeight; // calculates pending rewards to be added uint256 _rewards = userTotalWeight.earned( rewardsPerWeight, user.rewardsPerWeightPaid ); // calculates pending reenue distribution to be added // increases stored user.rewards with value returned user.pendingRewards += _rewards; // updates user checkpoint values for future calculations user.rewardsPerWeightPaid = rewardsPerWeight; // emits an event emit LogUpdateRewards(_staker, _rewards); } /** * * @dev Updates smart contract state (`rewardsPerWeight`, `lastRewardsDistribution`), * updates state via `updatePIKAPerSecond` */ function _sync() internal { IPoolController _poolController = IPoolController(poolController); if (_now256() <= lastRewardsDistribution) { return; } // if globalStakeWeight is zero - update only `lastRewardsDistribution` and exit if (globalStakeWeight == 0) { lastRewardsDistribution = _now256(); return; } // to calculate the reward we need to know how many seconds passed, and reward per second uint256 currentTimestamp = _now256(); uint256 secondsPassed = currentTimestamp - lastRewardsDistribution; // calculate the reward uint256 pikaReward = (secondsPassed * _poolController.pikaPerSecond() * weight) / _poolController.totalWeight(); // update rewards per weight and `lastRewardsDistribution` rewardsPerWeight += pikaReward.getRewardPerWeight(globalStakeWeight); lastRewardsDistribution = currentTimestamp; // emits an event emit LogSync(msg.sender, rewardsPerWeight, lastRewardsDistribution); } /** * @notice Service function to synchronize pool state with current time. * * @dev Can be executed by anyone at any time, but has an effect only when * at least one second passes between synchronizations. * @dev Executed internally when staking, unstaking, processing rewards in order * for calculations to be correct and to reflect state progress of the contract. * @dev When timing conditions are not met (executed too frequently, or after pool Controller * end time), function doesn't throw and exits silently. */ function sync() external { // checks if the contract is in a paused state if (paused()) revert CommonErrors.ContractIsPaused(); // calls internal function _sync(); } /** * @dev Executed by the pool Controller to modify pool weight; the pool Controller is expected * to keep track of the total pools weight when updating. * * @dev Set weight to zero to disable the pool. * * @param _weight new weight to set for the pool */ function setWeight(uint256 _weight) external { if (msg.sender != poolController) { revert CommonErrors.OnlyFactory(); } // update pool state using current weight value _sync(); // set the new weight value weight = _weight; } /** * @dev Set paused/unpaused state in the staking contract. * @param _shouldPause whether the contract should be paused/unpausd */ function pause(bool _shouldPause) external onlyOwner { if (_shouldPause) { _pause(); } else { _unpause(); } } /** * @dev set verification address for ECDSA claim verification. * @param _verifierAddress verifier Address */ function setVerifierAddress(address _verifierAddress) external onlyOwner { if (_verifierAddress == address(0)) revert CommonErrors.ZeroAddress(); emit LogVerificationAddress(_verifierAddress, verifierAddress); verifierAddress = _verifierAddress; } /** * @notice Returns total staked token balance for the given address. * @dev Loops through stakes and returns total balance. * @notice Expected to be called externally through `eth_call`. Gas shouldn't * be an issue here. * * @param _user an address to query balance for * @return balance total staked token balance */ function balanceOf(address _user) external view returns (uint256 balance) { // gets storage pointer to _user // storage takes less gas User storage user = users[_user]; // calculate length uint256 len = user.stakes.length; // loops over each user stake and adds to the total balance. for (uint256 i; i < len; i++) { if (!user.stakes[i].isUnstaked) { balance += user.stakes[i].value; } } } /** * @notice Returns number of stakes for the given address. Allows iteration over stakes. * * @dev See `getStake()`. * * @param _user an address to query stake length for * @return number of stakes for the given address */ function getStakesLength(address _user) external view returns (uint256) { // read stakes array length and return return users[_user].stakes.length; } /** * @notice Returns information on the given stake for the given address. * * @dev See getStakesLength. * * @param _user an address to query stake for * @param _stakeId zero-indexed stake ID for the address specified * @return stake info as Stake structure */ function getStake( address _user, uint256 _stakeId ) external view returns (Stake.Data memory) { // read stake at specified index and return return users[_user].stakes[_stakeId]; } /** * @dev Get paginated stake information for a specific user * * This function allows querying stake information for a specific user in a paginated manner. * Users can specify a start index and a count to retrieve a subset of the user's stakes. * * @param _user The address of the user to query stake information for * @param startIndex The start index of the paginated results (zero-indexed) * @param count The number of stake entries to retrieve * * @return result An array of Stake.Data structures containing paginated stake information */ function getPaginatedStake( address _user, uint startIndex, uint count ) external view returns (Stake.Data[] memory result) { // storage takes less gas Stake.Data[] storage data = users[_user].stakes; uint len = data.length; // Ensure that we are not starting the pagination out of the bounds of the array if (startIndex >= len) return result; // Calculate the actual number of items we can return uint length = count; if (startIndex + count > len) { length = len - startIndex; } // Allocate memory for the result array result = new Stake.Data[](length); // Populate the result array with the relevant data for (uint i = 0; i < length; ) { result[i] = data[startIndex + i]; unchecked { ++i; } } return result; } /** * @dev Testing time-dependent functionality is difficult and the best way of * doing it is to override time in helper test smart contracts. * * @return `block.timestamp` in mainnet, custom values in testnets (if overridden). */ function _now256() internal view virtual returns (uint256) { // return current block timestamp return block.timestamp; } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[37] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.20; interface IPoolController { function owner() external view returns (address); function pikaPerSecond() external view returns (uint192); function totalWeight() external view returns (uint32); function transferRewardTokens( address _token, address _to, uint256 _value ) external; function changePoolWeight(address pool, uint32 weight) external; function pools(address _poolToken) external view returns (address); function poolExists(address _poolAddress) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.20; import "../libraries/Stake.sol"; interface ICorePool { /* ========== MUTATIVE FUNCTIONS ========== */ function stake(uint256 _value, uint256 _lockDuration) external; function poolToken() external view returns (address); function stakeAsPool(address _staker, uint256 _value) external ; function unstake(uint256 _stakeId) external; function claimRewards( uint256 _claimPercentage, bool _restakeLeftOver, bytes memory _signature, uint256 _nonce ) external; function sync() external; function setWeight(uint256 _weight) external; /* ========== RESTRICTED FUNCTIONS ========== */ function pause(bool _shouldPause) external; /* ========== READ FUNCTIONS ========== */ function pendingRewards( address _staker ) external view returns (uint256 pendingYield); function balanceOf(address _user) external view returns (uint256 balance); function getStakesLength(address _user) external view returns (uint256); function getStake( address _user, uint256 _stakeId ) external view returns (Stake.Data memory); function weight() external view returns (uint256); /* ========== EVENTS ========== */ /** * @dev Fired in _stake() and stakeAsPool() in PIKAPool contract. * @param from token holder address, the tokens will be returned to that address * @param stakeId id of the new stake created * @param value value of tokens staked * @param lockUntil timestamp indicating when tokens should unlock (max 2 years) */ event LogStake( address indexed from, uint256 stakeId, uint256 value, uint256 lockUntil ); /** * @dev Fired in `_updateRewards()`. * * @param from an address which received the yield * @param yieldValue value of yield processed */ event LogUpdateRewards(address indexed from, uint256 yieldValue); /** * @dev Fired in `unstake()`. * * @param to address receiving the tokens (user) * @param stakeId id value of the stake * @param value number of tokens unstaked */ event LogUnstake( address indexed to, uint256 stakeId, uint256 value, uint256 earlyUnstakePercentage, bool isEarlyUnstake ); /** * @dev Fired in `updatePIKAPerSecond()`. * * @param by an address which executed an action * @param newPIKAPerSecond new PIKA/second value */ event LogUpdatePikaPerSecond(address indexed by, uint256 newPIKAPerSecond); /** * @dev Fired in `_sync()` and dependent functions (stake, unstake, etc.). * * @param by an address which performed an operation * @param yieldRewardsPerWeight updated yield rewards per weight value * @param lastYieldDistribution usually, current timestamp */ event LogSync( address indexed by, uint256 yieldRewardsPerWeight, uint256 lastYieldDistribution ); /** * @dev Fired in `updatePIKAPerSecond()`. * * @param by an address which executed an action * @param newPikaPerSecond new PIKA/second value */ event LogUpdatePIKAPerSecond(address indexed by, uint256 newPikaPerSecond); /** * @dev Fired in `_claimYieldRewards()`. * * @param from an address which received the yield * @param value value of yield paid */ event LogClaimRewards(address indexed from, uint256 value); /** * @dev Fired in `setEndTime()`. * * @param by an address which executed the action * @param endTime new endTime value */ event LogSetEndTime(address indexed by, uint256 endTime); /** * @dev Fired in `setsetVerifierAddress()`. * * @param newVerificationAddress new Verification Address * @param oldVerificationAddress old Verification Address */ event LogVerificationAddress(address indexed newVerificationAddress,address indexed oldVerificationAddress); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @dev This smart contract defines custom errors that can be thrown during specific conditions in contracts. * @notice Pre-defined errors instead of string error messages to reduce gas costs. */ library CommonErrors { error ZeroAmount(); error ZeroAddress(); error ContractIsPaused(); error InvalidLockDuration(); error OnlyFactory(); error AlreadyRegistered(); error WrongHash(); error AlreadyUnstaked(); error UnAuthorized(); error CoolOffPeriodIsNotOver(); error InvalidOperation(); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @dev Stake library used by PIKA pool and PIKA/USDT LP Pool. * * @dev Responsible to manage weight calculation and store important constants * related to stake period, base weight and multipliers utilized. */ library Stake { struct Data { /// @dev token amount staked uint256 value; /// @dev locking period - from uint256 lockedFrom; /// @dev locking period - until uint256 lockedUntil; /// @dev whether the entry is unstaked bool isUnstaked; /// @dev stakeId same as the array index uint256 stakeId; } /** * @dev Stake weight is proportional to stake value and time locked, precisely * "stake value wei multiplied by (fraction of the year locked plus one)". * @dev To avoid significant precision loss due to multiplication by "fraction of the year" [0, 1], * weight is stored multiplied by 1e6 constant, as an integer. * @dev Corner case 1: if time locked is zero, weight is stake value multiplied by 1e6 + base weight * @dev Corner case 2: if time locked is two years, division of (lockedUntil - lockedFrom) / MAX_STAKE_PERIOD is 1e6, and * weight is a stake value multiplied by 2 * 1e6. */ uint256 internal constant WEIGHT_MULTIPLIER = 1e6; /** * @dev Minimum weight value, if result of multiplication using WEIGHT_MULTIPLIER * is 0 (e.g stake flexible), then BASE_WEIGHT is used. */ uint256 internal constant BASE_WEIGHT = 1e6; /** * @dev Minimum period that someone can lock a stake for. */ uint256 internal constant MIN_STAKE_PERIOD = 30 days; /** * @dev Maximum period that someone can lock a stake for. */ uint256 internal constant MAX_STAKE_PERIOD = 365 days; /** * @dev Rewards per weight are stored multiplied by 1e20 as uint. */ uint256 internal constant REWARD_PER_WEIGHT_MULTIPLIER = 1e20; function weight(Data storage _self) internal view returns (uint256) { return uint256( (((_self.lockedUntil - _self.lockedFrom) * WEIGHT_MULTIPLIER) / MAX_STAKE_PERIOD + BASE_WEIGHT) * _self.value ); } /** * @dev Converts stake weight (not to be mixed with the pool weight) to * PIKA reward value, applying the 10^12 division on weight * * @param _weight stake weight * @param _rewardPerWeight PIKA reward per weight * @param _rewardPerWeightPaid last reward per weight value used for user earnings * @return reward value normalized to 10^12 */ function earned( uint256 _weight, uint256 _rewardPerWeight, uint256 _rewardPerWeightPaid ) internal pure returns (uint256) { // apply the formula and return return (_weight * (_rewardPerWeight - _rewardPerWeightPaid)) / REWARD_PER_WEIGHT_MULTIPLIER; } /** * @dev Converts reward PIKA value to stake weight (not to be mixed with the pool weight), * applying the 10^12 multiplication on the reward. * - OR - * @dev Converts reward PIKA value to reward/weight if stake weight is supplied as second * function parameter instead of reward/weight. * * @param _reward yield reward * @param _globalWeight total weight in the pool * @return reward per weight value */ function getRewardPerWeight(uint256 _reward, uint256 _globalWeight) internal pure returns (uint256) { // apply the reverse formula and return return (_reward * REWARD_PER_WEIGHT_MULTIPLIER) / _globalWeight; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.20; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; interface IPikaMoon is IERC20 { function mint(address to, uint amount) external; function burn(address owner, uint amount) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyUnstaked","type":"error"},{"inputs":[],"name":"ContractIsPaused","type":"error"},{"inputs":[],"name":"CoolOffPeriodIsNotOver","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLockDuration","type":"error"},{"inputs":[],"name":"InvalidOperation","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyFactory","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[],"name":"UnAuthorized","type":"error"},{"inputs":[],"name":"WrongHash","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"LogSetEndTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockUntil","type":"uint256"}],"name":"LogStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"yieldRewardsPerWeight","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastYieldDistribution","type":"uint256"}],"name":"LogSync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"earlyUnstakePercentage","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isEarlyUnstake","type":"bool"}],"name":"LogUnstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPikaPerSecond","type":"uint256"}],"name":"LogUpdatePIKAPerSecond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPIKAPerSecond","type":"uint256"}],"name":"LogUpdatePikaPerSecond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"yieldValue","type":"uint256"}],"name":"LogUpdateRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newVerificationAddress","type":"address"},{"indexed":true,"internalType":"address","name":"oldVerificationAddress","type":"address"}],"name":"LogVerificationAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockedFrom","type":"uint256"},{"internalType":"uint256","name":"nowTime","type":"uint256"},{"internalType":"uint256","name":"lockedUntil","type":"uint256"}],"name":"calculateEarlyUnstakePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimPercentage","type":"uint256"},{"internalType":"bool","name":"_restakeLeftOver","type":"bool"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"coolOffPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"getPaginatedStake","outputs":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"lockedFrom","type":"uint256"},{"internalType":"uint256","name":"lockedUntil","type":"uint256"},{"internalType":"bool","name":"isUnstaked","type":"bool"},{"internalType":"uint256","name":"stakeId","type":"uint256"}],"internalType":"struct Stake.Data[]","name":"result","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"getStake","outputs":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"lockedFrom","type":"uint256"},{"internalType":"uint256","name":"lockedUntil","type":"uint256"},{"internalType":"bool","name":"isUnstaked","type":"bool"},{"internalType":"uint256","name":"stakeId","type":"uint256"}],"internalType":"struct Stake.Data","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getStakesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalStakeWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_poolController","type":"address"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastRewardsDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lowerBoundSlash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldPause","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"_pendingRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"}],"name":"setVerifierAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"setWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"signatureUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_lockDuration","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"stakeAsPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalTokenStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"upperBoundSlash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint256","name":"pendingRewards","type":"uint256"},{"internalType":"uint256","name":"userTotalWeight","type":"uint256"},{"internalType":"uint256","name":"rewardsPerWeightPaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff1681525034801562000043575f80fd5b50620000546200005a60201b60201c565b620001c4565b5f6200006b6200015e60201b60201c565b9050805f0160089054906101000a900460ff1615620000b6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8016815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16146200015b5767ffffffffffffffff815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d267ffffffffffffffff604051620001529190620001a9565b60405180910390a15b50565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b5f67ffffffffffffffff82169050919050565b620001a38162000185565b82525050565b5f602082019050620001be5f83018462000198565b92915050565b608051614fd9620001eb5f395f8181612cc401528181612d190152612ed30152614fd95ff3fe60806040526004361061020e575f3560e01c80637644dcaa11610117578063cf73b3841161009f578063f2fde38b1161006e578063f2fde38b1461079c578063f7c618c1146107c4578063fc1711f2146107ee578063fc196d0814610816578063fff6cae9146108405761020e565b8063cf73b384146106c0578063cf756fdf146106fc578063cfd4766314610724578063e307fb31146107605761020e565b8063a1aab33f116100e6578063a1aab33f146105da578063a87430ba14610604578063ad3cb1cc14610642578063bd6f36031461066c578063cbdf382c146106965761020e565b80637644dcaa146105225780637b0472f01461054c5780638da5cb5b14610574578063909767d91461059e5761020e565b80634f1ef2861161019a578063623b4dcb11610169578063623b4dcb1461042e57806363fc7fe9146104585780636802aa681461049457806370a08231146104d0578063715018a61461050c5761020e565b80634f1ef2861461039657806352d1902d146103b25780635c975abb146103dc5780635fcd1800146104065761020e565b80632e559d79116101e15780632e559d79146102b45780632fa79ee5146102de57806331d7a2621461030857806344cc892d146103445780634aa9d5851461036c5761020e565b806302329a291461021257806317e955261461023a57806318bdffbb146102625780632e17de781461028c575b5f80fd5b34801561021d575f80fd5b5061023860048036038101906102339190613fa3565b610856565b005b348015610245575f80fd5b50610260600480360381019061025b9190614028565b61087d565b005b34801561026d575f80fd5b506102766109a8565b6040516102839190614062565b60405180910390f35b348015610297575f80fd5b506102b260048036038101906102ad91906140ae565b6109cd565b005b3480156102bf575f80fd5b506102c8610d96565b6040516102d591906140e8565b60405180910390f35b3480156102e9575f80fd5b506102f2610d9c565b6040516102ff91906140e8565b60405180910390f35b348015610313575f80fd5b5061032e60048036038101906103299190614028565b610da2565b60405161033b91906140e8565b60405180910390f35b34801561034f575f80fd5b5061036a60048036038101906103659190614101565b611030565b005b348015610377575f80fd5b50610380611411565b60405161038d9190614062565b60405180910390f35b6103b060048036038101906103ab919061427b565b611436565b005b3480156103bd575f80fd5b506103c6611455565b6040516103d391906142ed565b60405180910390f35b3480156103e7575f80fd5b506103f0611486565b6040516103fd9190614315565b60405180910390f35b348015610411575f80fd5b5061042c6004803603810190610427919061438b565b6114a8565b005b348015610439575f80fd5b50610442611d71565b60405161044f91906140e8565b60405180910390f35b348015610463575f80fd5b5061047e60048036038101906104799190614028565b611d77565b60405161048b91906140e8565b60405180910390f35b34801561049f575f80fd5b506104ba60048036038101906104b5919061440f565b611d8c565b6040516104c791906140e8565b60405180910390f35b3480156104db575f80fd5b506104f660048036038101906104f19190614028565b611e04565b60405161050391906140e8565b60405180910390f35b348015610517575f80fd5b50610520611ede565b005b34801561052d575f80fd5b50610536611ef1565b60405161054391906140e8565b60405180910390f35b348015610557575f80fd5b50610572600480360381019061056d919061445f565b611ef7565b005b34801561057f575f80fd5b50610588612233565b6040516105959190614062565b60405180910390f35b3480156105a9575f80fd5b506105c460048036038101906105bf9190614028565b612268565b6040516105d191906140e8565b60405180910390f35b3480156105e5575f80fd5b506105ee6122b4565b6040516105fb91906140e8565b60405180910390f35b34801561060f575f80fd5b5061062a60048036038101906106259190614028565b6122ba565b6040516106399392919061449d565b60405180910390f35b34801561064d575f80fd5b506106566122e0565b604051610663919061454c565b60405180910390f35b348015610677575f80fd5b50610680612319565b60405161068d91906140e8565b60405180910390f35b3480156106a1575f80fd5b506106aa61231f565b6040516106b79190614062565b60405180910390f35b3480156106cb575f80fd5b506106e660048036038101906106e1919061456c565b612344565b6040516106f391906146e8565b60405180910390f35b348015610707575f80fd5b50610722600480360381019061071d9190614708565b6124d0565b005b34801561072f575f80fd5b5061074a60048036038101906107459190614101565b612670565b60405161075791906147d2565b60405180910390f35b34801561076b575f80fd5b5061078660048036038101906107819190614815565b61272a565b6040516107939190614315565b60405180910390f35b3480156107a7575f80fd5b506107c260048036038101906107bd9190614028565b612747565b005b3480156107cf575f80fd5b506107d86127cb565b6040516107e59190614062565b60405180910390f35b3480156107f9575f80fd5b50610814600480360381019061080f91906140ae565b6127f0565b005b348015610821575f80fd5b5061082a612888565b60405161083791906140e8565b60405180910390f35b34801561084b575f80fd5b5061085461288d565b005b61085e6128d6565b80156108715761086c61295d565b61087a565b6108796129cc565b5b50565b6108856128d6565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108ea576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2d959f2f3c48bc44bb1da85e9430ff752f4604092d8d3f38421ae264cc86542660405160405180910390a38060055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6109d5611486565b15610a0c576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050610a5533612a3a565b5f816003018381548110610a6c57610a6b614840565b5b905f5260205f20906005020190505f815f01549050826003018481548110610a9757610a96614840565b5b905f5260205f2090600502016003015f9054906101000a900460ff1615610aea576040517fd831531200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610af483612b1e565b9050808460010154610b06919061489a565b846001018190555080600754610b1c919061489a565b6007819055508160085f828254610b33919061489a565b925050819055506001846003018681548110610b5257610b51614840565b5b905f5260205f2090600502016003015f6101000a81548160ff0219169083151502179055508260020154610b84612b73565b1015610cee575f610ba58460010154610b9b612b73565b8660020154611d8c565b90505f600b548285610bb791906148cd565b610bc1919061493b565b84610bcc919061489a565b9050610c4660045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168286610bff919061489a565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b610c92338260025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f3627975b28b74f1965a80e230770993136e2e9486705755206c93917dee8581f8883856001604051610cdf949392919061496b565b60405180910390a25050610d8f565b610d3a338360025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f3627975b28b74f1965a80e230770993136e2e9486705755206c93917dee8581f86845f80604051610d8694939291906149f0565b60405180910390a25b5050505050565b60085481565b60095481565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e08576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060015490505f600c5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f8160010154905082610e60612b73565b118015610e6f57505f60075414155b15610ff9575f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f84610ea3612b73565b610ead919061489a565b90505f8273ffffffffffffffffffffffffffffffffffffffff166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ef9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1d9190614a6c565b63ffffffff166006548473ffffffffffffffffffffffffffffffffffffffff166382378b9e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f939190614ae4565b77ffffffffffffffffffffffffffffffffffffffffffffffff1684610fb891906148cd565b610fc291906148cd565b610fcc919061493b565b90505f54610fe560075483612bf990919063ffffffff16565b610fef9190614b0f565b9650505050610ffe565b5f5493505b815f015461101b85846002015484612c229092919063ffffffff16565b6110259190614b0f565b945050505050919050565b611038612c57565b611040611486565b15611077576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16631e1c6a07336040518263ffffffff1660e01b81526004016110d59190614062565b602060405180830381865afa1580156110f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190614b56565b61114a576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061119384612a3a565b5f6301e133806111a1612b73565b6111ab9190614b0f565b90505f84620f42406301e13380620f42406111c4612b73565b866111cf919061489a565b6111d991906148cd565b6111e3919061493b565b6111ed9190614b0f565b6111f791906148cd565b90505f6040518060a00160405280878152602001611213612b73565b81526020018481526020015f151581526020018560030180549050815250905081846001015f8282546112469190614b0f565b925050819055508360030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff0219169083151502179055506080820151816004015550508160075f8282546112d09190614b0f565b925050819055508560085f8282546112e89190614b0f565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630896040518463ffffffff1660e01b815260040161136e93929190614b81565b5f604051808303815f87803b158015611385575f80fd5b505af1158015611397573d5f803e3d5ffd5b505050508673ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a7916361600186600301805490506113e7919061489a565b88866040516113f89392919061449d565b60405180910390a2505050505061140d612cab565b5050565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61143e612cc2565b61144782612da8565b6114518282612db3565b5050565b5f61145e612ed1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b905090565b5f80611490612f58565b9050805f015f9054906101000a900460ff1691505090565b6114b0611486565b156114e7576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b548511156114f5575f80fd5b8315801561150357505f8514155b1561159b5762278d0063ffffffff16600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461155a9190614b0f565b611562612b73565b101561159a576040517fbc7e2ab000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6115a3612b73565b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505f61161a338787856040516020016115ff9493929190614c60565b60405160208183030381529060405280519060200120612f7f565b9050600d5f8281526020019081526020015f205f9054906101000a900460ff1615611643575f80fd5b6001600d5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116f18286868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f82011690508083019250505050505050612fae565b73ffffffffffffffffffffffffffffffffffffffff161461173e576040517f65c12e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61174733612a3a565b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015403611798575050611d6a565b5f871480156117a5575085155b156117dc576040517f398d4d3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8714611917575f600b5488835f01546117f691906148cd565b611800919061493b565b905080825f015f828254611814919061489a565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633846040518463ffffffff1660e01b815260040161189a93929190614b81565b5f604051808303815f87803b1580156118b1575f80fd5b505af11580156118c3573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff167fd932483646bce6fad101b0c81e8ff57f1bbf042b139520474fb78e80755d2dab8260405161190d91906140e8565b60405180910390a2505b8580156119255750600b5487105b15611d675760035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611c2f575f815f015490505f825f01819055505f6301e133806119bc612b73565b6119c69190614b0f565b90505f82620f42406301e13380620f42406119df612b73565b866119ea919061489a565b6119f491906148cd565b6119fe919061493b565b611a089190614b0f565b611a1291906148cd565b90505f8111611a1f575f80fd5b5f6040518060a00160405280858152602001611a39612b73565b81526020018481526020015f15158152602001866003018054905081525090508460030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff02191690831515021790555060808201518160040155505081856001015f828254611ade9190614b0f565b925050819055508160075f828254611af69190614b0f565b925050819055508360085f828254611b0e9190614b0f565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630876040518463ffffffff1660e01b8152600401611b9493929190614b81565b5f604051808303815f87803b158015611bab575f80fd5b505af1158015611bbd573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a791636160018760030180549050611c0d919061489a565b8686604051611c1e9392919061449d565b60405180910390a250505050611d66565b5f815f015490505f825f01819055505f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a4063dbc60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401611cba9190614062565b602060405180830381865afa158015611cd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf99190614cc1565b90508073ffffffffffffffffffffffffffffffffffffffff166344cc892d33846040518363ffffffff1660e01b8152600401611d36929190614cec565b5f604051808303815f87803b158015611d4d575f80fd5b505af1158015611d5f573d5f803e3d5ffd5b5050505050505b5b50505b5050505050565b600a5481565b600e602052805f5260405f205f915090505481565b5f818311611df9575f8483611da1919061489a565b600b548585611db0919061489a565b611dba91906148cd565b611dc4919061493b565b9050600a54811015611ddb57600a54915050611dfd565b600954811115611df057600954915050611dfd565b80915050611dfd565b5f90505b9392505050565b5f80600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816003018054905090505f5b81811015611ed657826003018181548110611e7057611e6f614840565b5b905f5260205f2090600502016003015f9054906101000a900460ff16611ec357826003018181548110611ea657611ea5614840565b5b905f5260205f2090600502015f015484611ec09190614b0f565b93505b8080611ece90614d13565b915050611e52565b505050919050565b611ee66128d6565b611eef5f612fd8565b565b60075481565b611eff612c57565b611f07611486565b15611f3e576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8203611f77576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62278d008110158015611f8e57506301e133808111155b611fc4576040517f7cb179e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061200d33612a3a565b5f82612017612b73565b6120219190614b0f565b90505f84620f42406301e13380620f424061203a612b73565b86612045919061489a565b61204f91906148cd565b612059919061493b565b6120639190614b0f565b61206d91906148cd565b90505f811161207a575f80fd5b5f6040518060a00160405280878152602001612094612b73565b81526020018481526020015f15158152602001856003018054905081525090508360030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff02191690831515021790555060808201518160040155505081846001015f8282546121399190614b0f565b925050819055508160075f8282546121519190614b0f565b925050819055508560085f8282546121699190614b0f565b925050819055506121be33308860025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166130a9909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a79163616001866003018054905061220a919061489a565b888660405161221b9392919061449d565b60405180910390a25050505061222f612cab565b5050565b5f8061223d61312b565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b5f600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600301805490509050919050565b60065481565b600c602052805f5260405f205f91509050805f0154908060010154908060020154905083565b6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b60015481565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60605f600c5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060030190505f8180549050905080851061239f5750506124c9565b5f8490508185876123b09190614b0f565b11156123c55785826123c2919061489a565b90505b8067ffffffffffffffff8111156123df576123de614157565b5b60405190808252806020026020018201604052801561241857816020015b612405613f31565b8152602001906001900390816123fd5790505b5093505f5b818110156124c4578381886124329190614b0f565b8154811061244357612442614840565b5b905f5260205f2090600502016040518060a00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900460ff161515151581526020016004820154815250508582815181106124ae576124ad614840565b5b602002602001018190525080600101905061241d565b505050505b9392505050565b5f6124d9613152565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f808267ffffffffffffffff161480156125215750825b90505f60018367ffffffffffffffff1614801561255457505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015612562575080155b15612599576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083156125e6576001855f0160086101000a81548160ff0219169083151502179055505b6125ef33613179565b6125f761318d565b6125ff61319f565b61260b898989896131a9565b8315612665575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2600160405161265c9190614da6565b60405180910390a15b505050505050505050565b612678613f31565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060030182815481106126ca576126c9614840565b5b905f5260205f2090600502016040518060a00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900460ff16151515158152602001600482015481525050905092915050565b600d602052805f5260405f205f915054906101000a900460ff1681565b61274f6128d6565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036127bf575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016127b69190614062565b60405180910390fd5b6127c881612fd8565b50565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612876576040517f0c6d42ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61287e61341c565b8060068190555050565b5f5481565b612895611486565b156128cc576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128d461341c565b565b6128de61363b565b73ffffffffffffffffffffffffffffffffffffffff166128fc612233565b73ffffffffffffffffffffffffffffffffffffffff161461295b5761291f61363b565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016129529190614062565b60405180910390fd5b565b612965613642565b5f61296e612f58565b90506001815f015f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129b461363b565b6040516129c19190614062565b60405180910390a150565b6129d4613683565b5f6129dd612f58565b90505f815f015f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612a2261363b565b604051612a2f9190614062565b60405180910390a150565b612a4261341c565b5f600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816001015490505f612aa55f54846002015484612c229092919063ffffffff16565b905080835f015f828254612ab99190614b0f565b925050819055505f5483600201819055508373ffffffffffffffffffffffffffffffffffffffff167fbdb350188e9b2a4891f35e6dd30e2edc2663e108b92b7b862873de3c59cba2b582604051612b1091906140e8565b60405180910390a250505050565b5f815f0154620f42406301e13380620f424085600101548660020154612b44919061489a565b612b4e91906148cd565b612b58919061493b565b612b629190614b0f565b612b6c91906148cd565b9050919050565b5f42905090565b612bf4838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401612bad929190614cec565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506136c3565b505050565b5f8168056bc75e2d6310000084612c1091906148cd565b612c1a919061493b565b905092915050565b5f68056bc75e2d631000008284612c39919061489a565b85612c4491906148cd565b612c4e919061493b565b90509392505050565b5f612c60613758565b90506002815f015403612c9f576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002815f018190555050565b5f612cb4613758565b90506001815f018190555050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480612d6f57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612d5661377f565b73ffffffffffffffffffffffffffffffffffffffff1614155b15612da6576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b612db06128d6565b50565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e1b57506040513d601f19601f82011682018060405250810190612e189190614dd3565b60015b612e5c57816040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401612e539190614062565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b8114612ec257806040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600401612eb991906142ed565b60405180910390fd5b612ecc83836137d2565b505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614612f56576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300905090565b5f81604051602001612f919190614e72565b604051602081830303815290604052805190602001209050919050565b5f805f80612fbc8686613844565b925092509250612fcc8282613899565b82935050505092915050565b5f612fe161312b565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b613125848573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016130de93929190614b81565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506136c3565b50505050565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b6131816139fb565b61318a81613a3b565b50565b6131956139fb565b61319d613abf565b565b6131a76139fb565b565b6131b16139fb565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613216576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361327b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036132e0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6132e8612233565b60055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160045f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506133ef612b73565b600181905550806006819055506103846009819055506064600a819055506103e8600b8190555050505050565b5f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060015461344c612b73565b116134575750613639565b5f6007540361347457613468612b73565b60018190555050613639565b5f61347d612b73565b90505f6001548261348e919061489a565b90505f8373ffffffffffffffffffffffffffffffffffffffff166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134fe9190614a6c565b63ffffffff166006548573ffffffffffffffffffffffffffffffffffffffff166382378b9e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613550573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135749190614ae4565b77ffffffffffffffffffffffffffffffffffffffffffffffff168461359991906148cd565b6135a391906148cd565b6135ad919061493b565b90506135c460075482612bf990919063ffffffff16565b5f808282546135d39190614b0f565b92505081905550826001819055503373ffffffffffffffffffffffffffffffffffffffff167f3080b7bd2c324f74c283a191b34a0be31e6120cc0e3ab396119bb28365424cb85f5460015460405161362c929190614e97565b60405180910390a2505050505b565b5f33905090565b61364a611486565b15613681576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61368b611486565b6136c1576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f6136ed828473ffffffffffffffffffffffffffffffffffffffff16613aef90919063ffffffff16565b90505f81511415801561371157508080602001905181019061370f9190614b56565b155b1561375357826040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161374a9190614062565b60405180910390fd5b505050565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00905090565b5f6137ab7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b613b04565b5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6137db82613b0d565b8173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25f81511115613837576138318282613bd6565b50613840565b61383f613c56565b5b5050565b5f805f6041845103613884575f805f602087015192506040870151915060608701515f1a905061387688828585613c92565b955095509550505050613892565b5f600285515f1b9250925092505b9250925092565b5f60038111156138ac576138ab614ebe565b5b8260038111156138bf576138be614ebe565b5b03156139f757600160038111156138d9576138d8614ebe565b5b8260038111156138ec576138eb614ebe565b5b03613923576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600381111561393757613936614ebe565b5b82600381111561394a57613949614ebe565b5b0361398e57805f1c6040517ffce698f700000000000000000000000000000000000000000000000000000000815260040161398591906140e8565b60405180910390fd5b6003808111156139a1576139a0614ebe565b5b8260038111156139b4576139b3614ebe565b5b036139f657806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016139ed91906142ed565b60405180910390fd5b5b5050565b613a03613d79565b613a39576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b613a436139fb565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613ab3575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401613aaa9190614062565b60405180910390fd5b613abc81612fd8565b50565b613ac76139fb565b5f613ad0612f58565b90505f815f015f6101000a81548160ff02191690831515021790555050565b6060613afc83835f613d97565b905092915050565b5f819050919050565b5f8173ffffffffffffffffffffffffffffffffffffffff163b03613b6857806040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401613b5f9190614062565b60405180910390fd5b80613b947f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b613b04565b5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60605f808473ffffffffffffffffffffffffffffffffffffffff1684604051613bff9190614f2f565b5f60405180830381855af49150503d805f8114613c37576040519150601f19603f3d011682016040523d82523d5f602084013e613c3c565b606091505b5091509150613c4c858383613e60565b9250505092915050565b5f341115613c90576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115613cce575f600385925092509250613d6f565b5f6001888888886040515f8152602001604052604051613cf19493929190614f60565b6020604051602081039080840390855afa158015613d11573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613d62575f60015f801b93509350935050613d6f565b805f805f1b935093509350505b9450945094915050565b5f613d82613152565b5f0160089054906101000a900460ff16905090565b606081471015613dde57306040517fcd786059000000000000000000000000000000000000000000000000000000008152600401613dd59190614062565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff168486604051613e069190614f2f565b5f6040518083038185875af1925050503d805f8114613e40576040519150601f19603f3d011682016040523d82523d5f602084013e613e45565b606091505b5091509150613e55868383613e60565b925050509392505050565b606082613e7557613e7082613eed565b613ee5565b5f8251148015613e9b57505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15613edd57836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401613ed49190614062565b60405180910390fd5b819050613ee6565b5b9392505050565b5f81511115613eff5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060a001604052805f81526020015f81526020015f81526020015f151581526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f8115159050919050565b613f8281613f6e565b8114613f8c575f80fd5b50565b5f81359050613f9d81613f79565b92915050565b5f60208284031215613fb857613fb7613f66565b5b5f613fc584828501613f8f565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ff782613fce565b9050919050565b61400781613fed565b8114614011575f80fd5b50565b5f8135905061402281613ffe565b92915050565b5f6020828403121561403d5761403c613f66565b5b5f61404a84828501614014565b91505092915050565b61405c81613fed565b82525050565b5f6020820190506140755f830184614053565b92915050565b5f819050919050565b61408d8161407b565b8114614097575f80fd5b50565b5f813590506140a881614084565b92915050565b5f602082840312156140c3576140c2613f66565b5b5f6140d08482850161409a565b91505092915050565b6140e28161407b565b82525050565b5f6020820190506140fb5f8301846140d9565b92915050565b5f806040838503121561411757614116613f66565b5b5f61412485828601614014565b92505060206141358582860161409a565b9150509250929050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61418d82614147565b810181811067ffffffffffffffff821117156141ac576141ab614157565b5b80604052505050565b5f6141be613f5d565b90506141ca8282614184565b919050565b5f67ffffffffffffffff8211156141e9576141e8614157565b5b6141f282614147565b9050602081019050919050565b828183375f83830152505050565b5f61421f61421a846141cf565b6141b5565b90508281526020810184848401111561423b5761423a614143565b5b6142468482856141ff565b509392505050565b5f82601f8301126142625761426161413f565b5b813561427284826020860161420d565b91505092915050565b5f806040838503121561429157614290613f66565b5b5f61429e85828601614014565b925050602083013567ffffffffffffffff8111156142bf576142be613f6a565b5b6142cb8582860161424e565b9150509250929050565b5f819050919050565b6142e7816142d5565b82525050565b5f6020820190506143005f8301846142de565b92915050565b61430f81613f6e565b82525050565b5f6020820190506143285f830184614306565b92915050565b5f80fd5b5f80fd5b5f8083601f84011261434b5761434a61413f565b5b8235905067ffffffffffffffff8111156143685761436761432e565b5b60208301915083600182028301111561438457614383614332565b5b9250929050565b5f805f805f608086880312156143a4576143a3613f66565b5b5f6143b18882890161409a565b95505060206143c288828901613f8f565b945050604086013567ffffffffffffffff8111156143e3576143e2613f6a565b5b6143ef88828901614336565b935093505060606144028882890161409a565b9150509295509295909350565b5f805f6060848603121561442657614425613f66565b5b5f6144338682870161409a565b93505060206144448682870161409a565b92505060406144558682870161409a565b9150509250925092565b5f806040838503121561447557614474613f66565b5b5f6144828582860161409a565b92505060206144938582860161409a565b9150509250929050565b5f6060820190506144b05f8301866140d9565b6144bd60208301856140d9565b6144ca60408301846140d9565b949350505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156145095780820151818401526020810190506144ee565b5f8484015250505050565b5f61451e826144d2565b61452881856144dc565b93506145388185602086016144ec565b61454181614147565b840191505092915050565b5f6020820190508181035f8301526145648184614514565b905092915050565b5f805f6060848603121561458357614582613f66565b5b5f61459086828701614014565b93505060206145a18682870161409a565b92505060406145b28682870161409a565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6145ee8161407b565b82525050565b6145fd81613f6e565b82525050565b60a082015f8201516146175f8501826145e5565b50602082015161462a60208501826145e5565b50604082015161463d60408501826145e5565b50606082015161465060608501826145f4565b50608082015161466360808501826145e5565b50505050565b5f6146748383614603565b60a08301905092915050565b5f602082019050919050565b5f614696826145bc565b6146a081856145c6565b93506146ab836145d6565b805f5b838110156146db5781516146c28882614669565b97506146cd83614680565b9250506001810190506146ae565b5085935050505092915050565b5f6020820190508181035f830152614700818461468c565b905092915050565b5f805f80608085870312156147205761471f613f66565b5b5f61472d87828801614014565b945050602061473e87828801614014565b935050604061474f87828801614014565b92505060606147608782880161409a565b91505092959194509250565b60a082015f8201516147805f8501826145e5565b50602082015161479360208501826145e5565b5060408201516147a660408501826145e5565b5060608201516147b960608501826145f4565b5060808201516147cc60808501826145e5565b50505050565b5f60a0820190506147e55f83018461476c565b92915050565b6147f4816142d5565b81146147fe575f80fd5b50565b5f8135905061480f816147eb565b92915050565b5f6020828403121561482a57614829613f66565b5b5f61483784828501614801565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6148a48261407b565b91506148af8361407b565b92508282039050818111156148c7576148c661486d565b5b92915050565b5f6148d78261407b565b91506148e28361407b565b92508282026148f08161407b565b915082820484148315176149075761490661486d565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6149458261407b565b91506149508361407b565b9250826149605761495f61490e565b5b828204905092915050565b5f60808201905061497e5f8301876140d9565b61498b60208301866140d9565b61499860408301856140d9565b6149a56060830184614306565b95945050505050565b5f819050919050565b5f819050919050565b5f6149da6149d56149d0846149ae565b6149b7565b61407b565b9050919050565b6149ea816149c0565b82525050565b5f608082019050614a035f8301876140d9565b614a1060208301866140d9565b614a1d60408301856149e1565b614a2a6060830184614306565b95945050505050565b5f63ffffffff82169050919050565b614a4b81614a33565b8114614a55575f80fd5b50565b5f81519050614a6681614a42565b92915050565b5f60208284031215614a8157614a80613f66565b5b5f614a8e84828501614a58565b91505092915050565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b614ac381614a97565b8114614acd575f80fd5b50565b5f81519050614ade81614aba565b92915050565b5f60208284031215614af957614af8613f66565b5b5f614b0684828501614ad0565b91505092915050565b5f614b198261407b565b9150614b248361407b565b9250828201905080821115614b3c57614b3b61486d565b5b92915050565b5f81519050614b5081613f79565b92915050565b5f60208284031215614b6b57614b6a613f66565b5b5f614b7884828501614b42565b91505092915050565b5f606082019050614b945f830186614053565b614ba16020830185614053565b614bae60408301846140d9565b949350505050565b5f8160601b9050919050565b5f614bcc82614bb6565b9050919050565b5f614bdd82614bc2565b9050919050565b614bf5614bf082613fed565b614bd3565b82525050565b5f819050919050565b614c15614c108261407b565b614bfb565b82525050565b5f8160f81b9050919050565b5f614c3182614c1b565b9050919050565b5f614c4282614c27565b9050919050565b614c5a614c5582613f6e565b614c38565b82525050565b5f614c6b8287614be4565b601482019150614c7b8286614c04565b602082019150614c8b8285614c49565b600182019150614c9b8284614c04565b60208201915081905095945050505050565b5f81519050614cbb81613ffe565b92915050565b5f60208284031215614cd657614cd5613f66565b5b5f614ce384828501614cad565b91505092915050565b5f604082019050614cff5f830185614053565b614d0c60208301846140d9565b9392505050565b5f614d1d8261407b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d4f57614d4e61486d565b5b600182019050919050565b5f819050919050565b5f67ffffffffffffffff82169050919050565b5f614d90614d8b614d8684614d5a565b6149b7565b614d63565b9050919050565b614da081614d76565b82525050565b5f602082019050614db95f830184614d97565b92915050565b5f81519050614dcd816147eb565b92915050565b5f60208284031215614de857614de7613f66565b5b5f614df584828501614dbf565b91505092915050565b5f81905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f82015250565b5f614e3c601c83614dfe565b9150614e4782614e08565b601c82019050919050565b5f819050919050565b614e6c614e67826142d5565b614e52565b82525050565b5f614e7c82614e30565b9150614e888284614e5b565b60208201915081905092915050565b5f604082019050614eaa5f8301856140d9565b614eb760208301846140d9565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f81519050919050565b5f81905092915050565b5f614f0982614eeb565b614f138185614ef5565b9350614f238185602086016144ec565b80840191505092915050565b5f614f3a8284614eff565b915081905092915050565b5f60ff82169050919050565b614f5a81614f45565b82525050565b5f608082019050614f735f8301876142de565b614f806020830186614f51565b614f8d60408301856142de565b614f9a60608301846142de565b9594505050505056fea26469706673582212203ef92f74ae6d571a38f75a531fa7337d82fb2399eae3d01a91a8321a4caef8a664736f6c63430008140033
Deployed Bytecode
0x60806040526004361061020e575f3560e01c80637644dcaa11610117578063cf73b3841161009f578063f2fde38b1161006e578063f2fde38b1461079c578063f7c618c1146107c4578063fc1711f2146107ee578063fc196d0814610816578063fff6cae9146108405761020e565b8063cf73b384146106c0578063cf756fdf146106fc578063cfd4766314610724578063e307fb31146107605761020e565b8063a1aab33f116100e6578063a1aab33f146105da578063a87430ba14610604578063ad3cb1cc14610642578063bd6f36031461066c578063cbdf382c146106965761020e565b80637644dcaa146105225780637b0472f01461054c5780638da5cb5b14610574578063909767d91461059e5761020e565b80634f1ef2861161019a578063623b4dcb11610169578063623b4dcb1461042e57806363fc7fe9146104585780636802aa681461049457806370a08231146104d0578063715018a61461050c5761020e565b80634f1ef2861461039657806352d1902d146103b25780635c975abb146103dc5780635fcd1800146104065761020e565b80632e559d79116101e15780632e559d79146102b45780632fa79ee5146102de57806331d7a2621461030857806344cc892d146103445780634aa9d5851461036c5761020e565b806302329a291461021257806317e955261461023a57806318bdffbb146102625780632e17de781461028c575b5f80fd5b34801561021d575f80fd5b5061023860048036038101906102339190613fa3565b610856565b005b348015610245575f80fd5b50610260600480360381019061025b9190614028565b61087d565b005b34801561026d575f80fd5b506102766109a8565b6040516102839190614062565b60405180910390f35b348015610297575f80fd5b506102b260048036038101906102ad91906140ae565b6109cd565b005b3480156102bf575f80fd5b506102c8610d96565b6040516102d591906140e8565b60405180910390f35b3480156102e9575f80fd5b506102f2610d9c565b6040516102ff91906140e8565b60405180910390f35b348015610313575f80fd5b5061032e60048036038101906103299190614028565b610da2565b60405161033b91906140e8565b60405180910390f35b34801561034f575f80fd5b5061036a60048036038101906103659190614101565b611030565b005b348015610377575f80fd5b50610380611411565b60405161038d9190614062565b60405180910390f35b6103b060048036038101906103ab919061427b565b611436565b005b3480156103bd575f80fd5b506103c6611455565b6040516103d391906142ed565b60405180910390f35b3480156103e7575f80fd5b506103f0611486565b6040516103fd9190614315565b60405180910390f35b348015610411575f80fd5b5061042c6004803603810190610427919061438b565b6114a8565b005b348015610439575f80fd5b50610442611d71565b60405161044f91906140e8565b60405180910390f35b348015610463575f80fd5b5061047e60048036038101906104799190614028565b611d77565b60405161048b91906140e8565b60405180910390f35b34801561049f575f80fd5b506104ba60048036038101906104b5919061440f565b611d8c565b6040516104c791906140e8565b60405180910390f35b3480156104db575f80fd5b506104f660048036038101906104f19190614028565b611e04565b60405161050391906140e8565b60405180910390f35b348015610517575f80fd5b50610520611ede565b005b34801561052d575f80fd5b50610536611ef1565b60405161054391906140e8565b60405180910390f35b348015610557575f80fd5b50610572600480360381019061056d919061445f565b611ef7565b005b34801561057f575f80fd5b50610588612233565b6040516105959190614062565b60405180910390f35b3480156105a9575f80fd5b506105c460048036038101906105bf9190614028565b612268565b6040516105d191906140e8565b60405180910390f35b3480156105e5575f80fd5b506105ee6122b4565b6040516105fb91906140e8565b60405180910390f35b34801561060f575f80fd5b5061062a60048036038101906106259190614028565b6122ba565b6040516106399392919061449d565b60405180910390f35b34801561064d575f80fd5b506106566122e0565b604051610663919061454c565b60405180910390f35b348015610677575f80fd5b50610680612319565b60405161068d91906140e8565b60405180910390f35b3480156106a1575f80fd5b506106aa61231f565b6040516106b79190614062565b60405180910390f35b3480156106cb575f80fd5b506106e660048036038101906106e1919061456c565b612344565b6040516106f391906146e8565b60405180910390f35b348015610707575f80fd5b50610722600480360381019061071d9190614708565b6124d0565b005b34801561072f575f80fd5b5061074a60048036038101906107459190614101565b612670565b60405161075791906147d2565b60405180910390f35b34801561076b575f80fd5b5061078660048036038101906107819190614815565b61272a565b6040516107939190614315565b60405180910390f35b3480156107a7575f80fd5b506107c260048036038101906107bd9190614028565b612747565b005b3480156107cf575f80fd5b506107d86127cb565b6040516107e59190614062565b60405180910390f35b3480156107f9575f80fd5b50610814600480360381019061080f91906140ae565b6127f0565b005b348015610821575f80fd5b5061082a612888565b60405161083791906140e8565b60405180910390f35b34801561084b575f80fd5b5061085461288d565b005b61085e6128d6565b80156108715761086c61295d565b61087a565b6108796129cc565b5b50565b6108856128d6565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108ea576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2d959f2f3c48bc44bb1da85e9430ff752f4604092d8d3f38421ae264cc86542660405160405180910390a38060055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6109d5611486565b15610a0c576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050610a5533612a3a565b5f816003018381548110610a6c57610a6b614840565b5b905f5260205f20906005020190505f815f01549050826003018481548110610a9757610a96614840565b5b905f5260205f2090600502016003015f9054906101000a900460ff1615610aea576040517fd831531200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610af483612b1e565b9050808460010154610b06919061489a565b846001018190555080600754610b1c919061489a565b6007819055508160085f828254610b33919061489a565b925050819055506001846003018681548110610b5257610b51614840565b5b905f5260205f2090600502016003015f6101000a81548160ff0219169083151502179055508260020154610b84612b73565b1015610cee575f610ba58460010154610b9b612b73565b8660020154611d8c565b90505f600b548285610bb791906148cd565b610bc1919061493b565b84610bcc919061489a565b9050610c4660045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168286610bff919061489a565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b610c92338260025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f3627975b28b74f1965a80e230770993136e2e9486705755206c93917dee8581f8883856001604051610cdf949392919061496b565b60405180910390a25050610d8f565b610d3a338360025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b7a9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f3627975b28b74f1965a80e230770993136e2e9486705755206c93917dee8581f86845f80604051610d8694939291906149f0565b60405180910390a25b5050505050565b60085481565b60095481565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e08576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060015490505f600c5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f8160010154905082610e60612b73565b118015610e6f57505f60075414155b15610ff9575f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f84610ea3612b73565b610ead919061489a565b90505f8273ffffffffffffffffffffffffffffffffffffffff166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ef9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1d9190614a6c565b63ffffffff166006548473ffffffffffffffffffffffffffffffffffffffff166382378b9e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f939190614ae4565b77ffffffffffffffffffffffffffffffffffffffffffffffff1684610fb891906148cd565b610fc291906148cd565b610fcc919061493b565b90505f54610fe560075483612bf990919063ffffffff16565b610fef9190614b0f565b9650505050610ffe565b5f5493505b815f015461101b85846002015484612c229092919063ffffffff16565b6110259190614b0f565b945050505050919050565b611038612c57565b611040611486565b15611077576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16631e1c6a07336040518263ffffffff1660e01b81526004016110d59190614062565b602060405180830381865afa1580156110f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190614b56565b61114a576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061119384612a3a565b5f6301e133806111a1612b73565b6111ab9190614b0f565b90505f84620f42406301e13380620f42406111c4612b73565b866111cf919061489a565b6111d991906148cd565b6111e3919061493b565b6111ed9190614b0f565b6111f791906148cd565b90505f6040518060a00160405280878152602001611213612b73565b81526020018481526020015f151581526020018560030180549050815250905081846001015f8282546112469190614b0f565b925050819055508360030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff0219169083151502179055506080820151816004015550508160075f8282546112d09190614b0f565b925050819055508560085f8282546112e89190614b0f565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630896040518463ffffffff1660e01b815260040161136e93929190614b81565b5f604051808303815f87803b158015611385575f80fd5b505af1158015611397573d5f803e3d5ffd5b505050508673ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a7916361600186600301805490506113e7919061489a565b88866040516113f89392919061449d565b60405180910390a2505050505061140d612cab565b5050565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61143e612cc2565b61144782612da8565b6114518282612db3565b5050565b5f61145e612ed1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b905090565b5f80611490612f58565b9050805f015f9054906101000a900460ff1691505090565b6114b0611486565b156114e7576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b548511156114f5575f80fd5b8315801561150357505f8514155b1561159b5762278d0063ffffffff16600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461155a9190614b0f565b611562612b73565b101561159a576040517fbc7e2ab000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6115a3612b73565b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505f61161a338787856040516020016115ff9493929190614c60565b60405160208183030381529060405280519060200120612f7f565b9050600d5f8281526020019081526020015f205f9054906101000a900460ff1615611643575f80fd5b6001600d5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116f18286868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f82011690508083019250505050505050612fae565b73ffffffffffffffffffffffffffffffffffffffff161461173e576040517f65c12e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61174733612a3a565b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015403611798575050611d6a565b5f871480156117a5575085155b156117dc576040517f398d4d3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8714611917575f600b5488835f01546117f691906148cd565b611800919061493b565b905080825f015f828254611814919061489a565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633846040518463ffffffff1660e01b815260040161189a93929190614b81565b5f604051808303815f87803b1580156118b1575f80fd5b505af11580156118c3573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff167fd932483646bce6fad101b0c81e8ff57f1bbf042b139520474fb78e80755d2dab8260405161190d91906140e8565b60405180910390a2505b8580156119255750600b5487105b15611d675760035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611c2f575f815f015490505f825f01819055505f6301e133806119bc612b73565b6119c69190614b0f565b90505f82620f42406301e13380620f42406119df612b73565b866119ea919061489a565b6119f491906148cd565b6119fe919061493b565b611a089190614b0f565b611a1291906148cd565b90505f8111611a1f575f80fd5b5f6040518060a00160405280858152602001611a39612b73565b81526020018481526020015f15158152602001866003018054905081525090508460030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff02191690831515021790555060808201518160040155505081856001015f828254611ade9190614b0f565b925050819055508160075f828254611af69190614b0f565b925050819055508360085f828254611b0e9190614b0f565b9250508190555060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f35f116360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630876040518463ffffffff1660e01b8152600401611b9493929190614b81565b5f604051808303815f87803b158015611bab575f80fd5b505af1158015611bbd573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a791636160018760030180549050611c0d919061489a565b8686604051611c1e9392919061449d565b60405180910390a250505050611d66565b5f815f015490505f825f01819055505f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a4063dbc60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401611cba9190614062565b602060405180830381865afa158015611cd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf99190614cc1565b90508073ffffffffffffffffffffffffffffffffffffffff166344cc892d33846040518363ffffffff1660e01b8152600401611d36929190614cec565b5f604051808303815f87803b158015611d4d575f80fd5b505af1158015611d5f573d5f803e3d5ffd5b5050505050505b5b50505b5050505050565b600a5481565b600e602052805f5260405f205f915090505481565b5f818311611df9575f8483611da1919061489a565b600b548585611db0919061489a565b611dba91906148cd565b611dc4919061493b565b9050600a54811015611ddb57600a54915050611dfd565b600954811115611df057600954915050611dfd565b80915050611dfd565b5f90505b9392505050565b5f80600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816003018054905090505f5b81811015611ed657826003018181548110611e7057611e6f614840565b5b905f5260205f2090600502016003015f9054906101000a900460ff16611ec357826003018181548110611ea657611ea5614840565b5b905f5260205f2090600502015f015484611ec09190614b0f565b93505b8080611ece90614d13565b915050611e52565b505050919050565b611ee66128d6565b611eef5f612fd8565b565b60075481565b611eff612c57565b611f07611486565b15611f3e576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8203611f77576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62278d008110158015611f8e57506301e133808111155b611fc4576040517f7cb179e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061200d33612a3a565b5f82612017612b73565b6120219190614b0f565b90505f84620f42406301e13380620f424061203a612b73565b86612045919061489a565b61204f91906148cd565b612059919061493b565b6120639190614b0f565b61206d91906148cd565b90505f811161207a575f80fd5b5f6040518060a00160405280878152602001612094612b73565b81526020018481526020015f15158152602001856003018054905081525090508360030181908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff02191690831515021790555060808201518160040155505081846001015f8282546121399190614b0f565b925050819055508160075f8282546121519190614b0f565b925050819055508560085f8282546121699190614b0f565b925050819055506121be33308860025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166130a9909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f240ffe8e427179ca630e5deb6609b12883d4f986906749a6727b7ff6a79163616001866003018054905061220a919061489a565b888660405161221b9392919061449d565b60405180910390a25050505061222f612cab565b5050565b5f8061223d61312b565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b5f600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600301805490509050919050565b60065481565b600c602052805f5260405f205f91509050805f0154908060010154908060020154905083565b6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b60015481565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60605f600c5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060030190505f8180549050905080851061239f5750506124c9565b5f8490508185876123b09190614b0f565b11156123c55785826123c2919061489a565b90505b8067ffffffffffffffff8111156123df576123de614157565b5b60405190808252806020026020018201604052801561241857816020015b612405613f31565b8152602001906001900390816123fd5790505b5093505f5b818110156124c4578381886124329190614b0f565b8154811061244357612442614840565b5b905f5260205f2090600502016040518060a00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900460ff161515151581526020016004820154815250508582815181106124ae576124ad614840565b5b602002602001018190525080600101905061241d565b505050505b9392505050565b5f6124d9613152565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f808267ffffffffffffffff161480156125215750825b90505f60018367ffffffffffffffff1614801561255457505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015612562575080155b15612599576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083156125e6576001855f0160086101000a81548160ff0219169083151502179055505b6125ef33613179565b6125f761318d565b6125ff61319f565b61260b898989896131a9565b8315612665575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2600160405161265c9190614da6565b60405180910390a15b505050505050505050565b612678613f31565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060030182815481106126ca576126c9614840565b5b905f5260205f2090600502016040518060a00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900460ff16151515158152602001600482015481525050905092915050565b600d602052805f5260405f205f915054906101000a900460ff1681565b61274f6128d6565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036127bf575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016127b69190614062565b60405180910390fd5b6127c881612fd8565b50565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612876576040517f0c6d42ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61287e61341c565b8060068190555050565b5f5481565b612895611486565b156128cc576040517f6d39fcd000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128d461341c565b565b6128de61363b565b73ffffffffffffffffffffffffffffffffffffffff166128fc612233565b73ffffffffffffffffffffffffffffffffffffffff161461295b5761291f61363b565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016129529190614062565b60405180910390fd5b565b612965613642565b5f61296e612f58565b90506001815f015f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129b461363b565b6040516129c19190614062565b60405180910390a150565b6129d4613683565b5f6129dd612f58565b90505f815f015f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612a2261363b565b604051612a2f9190614062565b60405180910390a150565b612a4261341c565b5f600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816001015490505f612aa55f54846002015484612c229092919063ffffffff16565b905080835f015f828254612ab99190614b0f565b925050819055505f5483600201819055508373ffffffffffffffffffffffffffffffffffffffff167fbdb350188e9b2a4891f35e6dd30e2edc2663e108b92b7b862873de3c59cba2b582604051612b1091906140e8565b60405180910390a250505050565b5f815f0154620f42406301e13380620f424085600101548660020154612b44919061489a565b612b4e91906148cd565b612b58919061493b565b612b629190614b0f565b612b6c91906148cd565b9050919050565b5f42905090565b612bf4838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401612bad929190614cec565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506136c3565b505050565b5f8168056bc75e2d6310000084612c1091906148cd565b612c1a919061493b565b905092915050565b5f68056bc75e2d631000008284612c39919061489a565b85612c4491906148cd565b612c4e919061493b565b90509392505050565b5f612c60613758565b90506002815f015403612c9f576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002815f018190555050565b5f612cb4613758565b90506001815f018190555050565b7f0000000000000000000000009e6ed80e5d570be7012b3077f84c0b6c6bb3bd8373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480612d6f57507f0000000000000000000000009e6ed80e5d570be7012b3077f84c0b6c6bb3bd8373ffffffffffffffffffffffffffffffffffffffff16612d5661377f565b73ffffffffffffffffffffffffffffffffffffffff1614155b15612da6576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b612db06128d6565b50565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e1b57506040513d601f19601f82011682018060405250810190612e189190614dd3565b60015b612e5c57816040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401612e539190614062565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b8114612ec257806040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600401612eb991906142ed565b60405180910390fd5b612ecc83836137d2565b505050565b7f0000000000000000000000009e6ed80e5d570be7012b3077f84c0b6c6bb3bd8373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614612f56576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300905090565b5f81604051602001612f919190614e72565b604051602081830303815290604052805190602001209050919050565b5f805f80612fbc8686613844565b925092509250612fcc8282613899565b82935050505092915050565b5f612fe161312b565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b613125848573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016130de93929190614b81565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506136c3565b50505050565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b6131816139fb565b61318a81613a3b565b50565b6131956139fb565b61319d613abf565b565b6131a76139fb565b565b6131b16139fb565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613216576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361327b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036132e0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6132e8612233565b60055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160045f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506133ef612b73565b600181905550806006819055506103846009819055506064600a819055506103e8600b8190555050505050565b5f60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060015461344c612b73565b116134575750613639565b5f6007540361347457613468612b73565b60018190555050613639565b5f61347d612b73565b90505f6001548261348e919061489a565b90505f8373ffffffffffffffffffffffffffffffffffffffff166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134fe9190614a6c565b63ffffffff166006548573ffffffffffffffffffffffffffffffffffffffff166382378b9e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613550573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135749190614ae4565b77ffffffffffffffffffffffffffffffffffffffffffffffff168461359991906148cd565b6135a391906148cd565b6135ad919061493b565b90506135c460075482612bf990919063ffffffff16565b5f808282546135d39190614b0f565b92505081905550826001819055503373ffffffffffffffffffffffffffffffffffffffff167f3080b7bd2c324f74c283a191b34a0be31e6120cc0e3ab396119bb28365424cb85f5460015460405161362c929190614e97565b60405180910390a2505050505b565b5f33905090565b61364a611486565b15613681576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61368b611486565b6136c1576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f6136ed828473ffffffffffffffffffffffffffffffffffffffff16613aef90919063ffffffff16565b90505f81511415801561371157508080602001905181019061370f9190614b56565b155b1561375357826040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161374a9190614062565b60405180910390fd5b505050565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00905090565b5f6137ab7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b613b04565b5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6137db82613b0d565b8173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25f81511115613837576138318282613bd6565b50613840565b61383f613c56565b5b5050565b5f805f6041845103613884575f805f602087015192506040870151915060608701515f1a905061387688828585613c92565b955095509550505050613892565b5f600285515f1b9250925092505b9250925092565b5f60038111156138ac576138ab614ebe565b5b8260038111156138bf576138be614ebe565b5b03156139f757600160038111156138d9576138d8614ebe565b5b8260038111156138ec576138eb614ebe565b5b03613923576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600381111561393757613936614ebe565b5b82600381111561394a57613949614ebe565b5b0361398e57805f1c6040517ffce698f700000000000000000000000000000000000000000000000000000000815260040161398591906140e8565b60405180910390fd5b6003808111156139a1576139a0614ebe565b5b8260038111156139b4576139b3614ebe565b5b036139f657806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016139ed91906142ed565b60405180910390fd5b5b5050565b613a03613d79565b613a39576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b613a436139fb565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613ab3575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401613aaa9190614062565b60405180910390fd5b613abc81612fd8565b50565b613ac76139fb565b5f613ad0612f58565b90505f815f015f6101000a81548160ff02191690831515021790555050565b6060613afc83835f613d97565b905092915050565b5f819050919050565b5f8173ffffffffffffffffffffffffffffffffffffffff163b03613b6857806040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401613b5f9190614062565b60405180910390fd5b80613b947f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b613b04565b5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60605f808473ffffffffffffffffffffffffffffffffffffffff1684604051613bff9190614f2f565b5f60405180830381855af49150503d805f8114613c37576040519150601f19603f3d011682016040523d82523d5f602084013e613c3c565b606091505b5091509150613c4c858383613e60565b9250505092915050565b5f341115613c90576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115613cce575f600385925092509250613d6f565b5f6001888888886040515f8152602001604052604051613cf19493929190614f60565b6020604051602081039080840390855afa158015613d11573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613d62575f60015f801b93509350935050613d6f565b805f805f1b935093509350505b9450945094915050565b5f613d82613152565b5f0160089054906101000a900460ff16905090565b606081471015613dde57306040517fcd786059000000000000000000000000000000000000000000000000000000008152600401613dd59190614062565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff168486604051613e069190614f2f565b5f6040518083038185875af1925050503d805f8114613e40576040519150601f19603f3d011682016040523d82523d5f602084013e613e45565b606091505b5091509150613e55868383613e60565b925050509392505050565b606082613e7557613e7082613eed565b613ee5565b5f8251148015613e9b57505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15613edd57836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401613ed49190614062565b60405180910390fd5b819050613ee6565b5b9392505050565b5f81511115613eff5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060a001604052805f81526020015f81526020015f81526020015f151581526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f8115159050919050565b613f8281613f6e565b8114613f8c575f80fd5b50565b5f81359050613f9d81613f79565b92915050565b5f60208284031215613fb857613fb7613f66565b5b5f613fc584828501613f8f565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ff782613fce565b9050919050565b61400781613fed565b8114614011575f80fd5b50565b5f8135905061402281613ffe565b92915050565b5f6020828403121561403d5761403c613f66565b5b5f61404a84828501614014565b91505092915050565b61405c81613fed565b82525050565b5f6020820190506140755f830184614053565b92915050565b5f819050919050565b61408d8161407b565b8114614097575f80fd5b50565b5f813590506140a881614084565b92915050565b5f602082840312156140c3576140c2613f66565b5b5f6140d08482850161409a565b91505092915050565b6140e28161407b565b82525050565b5f6020820190506140fb5f8301846140d9565b92915050565b5f806040838503121561411757614116613f66565b5b5f61412485828601614014565b92505060206141358582860161409a565b9150509250929050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61418d82614147565b810181811067ffffffffffffffff821117156141ac576141ab614157565b5b80604052505050565b5f6141be613f5d565b90506141ca8282614184565b919050565b5f67ffffffffffffffff8211156141e9576141e8614157565b5b6141f282614147565b9050602081019050919050565b828183375f83830152505050565b5f61421f61421a846141cf565b6141b5565b90508281526020810184848401111561423b5761423a614143565b5b6142468482856141ff565b509392505050565b5f82601f8301126142625761426161413f565b5b813561427284826020860161420d565b91505092915050565b5f806040838503121561429157614290613f66565b5b5f61429e85828601614014565b925050602083013567ffffffffffffffff8111156142bf576142be613f6a565b5b6142cb8582860161424e565b9150509250929050565b5f819050919050565b6142e7816142d5565b82525050565b5f6020820190506143005f8301846142de565b92915050565b61430f81613f6e565b82525050565b5f6020820190506143285f830184614306565b92915050565b5f80fd5b5f80fd5b5f8083601f84011261434b5761434a61413f565b5b8235905067ffffffffffffffff8111156143685761436761432e565b5b60208301915083600182028301111561438457614383614332565b5b9250929050565b5f805f805f608086880312156143a4576143a3613f66565b5b5f6143b18882890161409a565b95505060206143c288828901613f8f565b945050604086013567ffffffffffffffff8111156143e3576143e2613f6a565b5b6143ef88828901614336565b935093505060606144028882890161409a565b9150509295509295909350565b5f805f6060848603121561442657614425613f66565b5b5f6144338682870161409a565b93505060206144448682870161409a565b92505060406144558682870161409a565b9150509250925092565b5f806040838503121561447557614474613f66565b5b5f6144828582860161409a565b92505060206144938582860161409a565b9150509250929050565b5f6060820190506144b05f8301866140d9565b6144bd60208301856140d9565b6144ca60408301846140d9565b949350505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156145095780820151818401526020810190506144ee565b5f8484015250505050565b5f61451e826144d2565b61452881856144dc565b93506145388185602086016144ec565b61454181614147565b840191505092915050565b5f6020820190508181035f8301526145648184614514565b905092915050565b5f805f6060848603121561458357614582613f66565b5b5f61459086828701614014565b93505060206145a18682870161409a565b92505060406145b28682870161409a565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6145ee8161407b565b82525050565b6145fd81613f6e565b82525050565b60a082015f8201516146175f8501826145e5565b50602082015161462a60208501826145e5565b50604082015161463d60408501826145e5565b50606082015161465060608501826145f4565b50608082015161466360808501826145e5565b50505050565b5f6146748383614603565b60a08301905092915050565b5f602082019050919050565b5f614696826145bc565b6146a081856145c6565b93506146ab836145d6565b805f5b838110156146db5781516146c28882614669565b97506146cd83614680565b9250506001810190506146ae565b5085935050505092915050565b5f6020820190508181035f830152614700818461468c565b905092915050565b5f805f80608085870312156147205761471f613f66565b5b5f61472d87828801614014565b945050602061473e87828801614014565b935050604061474f87828801614014565b92505060606147608782880161409a565b91505092959194509250565b60a082015f8201516147805f8501826145e5565b50602082015161479360208501826145e5565b5060408201516147a660408501826145e5565b5060608201516147b960608501826145f4565b5060808201516147cc60808501826145e5565b50505050565b5f60a0820190506147e55f83018461476c565b92915050565b6147f4816142d5565b81146147fe575f80fd5b50565b5f8135905061480f816147eb565b92915050565b5f6020828403121561482a57614829613f66565b5b5f61483784828501614801565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6148a48261407b565b91506148af8361407b565b92508282039050818111156148c7576148c661486d565b5b92915050565b5f6148d78261407b565b91506148e28361407b565b92508282026148f08161407b565b915082820484148315176149075761490661486d565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6149458261407b565b91506149508361407b565b9250826149605761495f61490e565b5b828204905092915050565b5f60808201905061497e5f8301876140d9565b61498b60208301866140d9565b61499860408301856140d9565b6149a56060830184614306565b95945050505050565b5f819050919050565b5f819050919050565b5f6149da6149d56149d0846149ae565b6149b7565b61407b565b9050919050565b6149ea816149c0565b82525050565b5f608082019050614a035f8301876140d9565b614a1060208301866140d9565b614a1d60408301856149e1565b614a2a6060830184614306565b95945050505050565b5f63ffffffff82169050919050565b614a4b81614a33565b8114614a55575f80fd5b50565b5f81519050614a6681614a42565b92915050565b5f60208284031215614a8157614a80613f66565b5b5f614a8e84828501614a58565b91505092915050565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b614ac381614a97565b8114614acd575f80fd5b50565b5f81519050614ade81614aba565b92915050565b5f60208284031215614af957614af8613f66565b5b5f614b0684828501614ad0565b91505092915050565b5f614b198261407b565b9150614b248361407b565b9250828201905080821115614b3c57614b3b61486d565b5b92915050565b5f81519050614b5081613f79565b92915050565b5f60208284031215614b6b57614b6a613f66565b5b5f614b7884828501614b42565b91505092915050565b5f606082019050614b945f830186614053565b614ba16020830185614053565b614bae60408301846140d9565b949350505050565b5f8160601b9050919050565b5f614bcc82614bb6565b9050919050565b5f614bdd82614bc2565b9050919050565b614bf5614bf082613fed565b614bd3565b82525050565b5f819050919050565b614c15614c108261407b565b614bfb565b82525050565b5f8160f81b9050919050565b5f614c3182614c1b565b9050919050565b5f614c4282614c27565b9050919050565b614c5a614c5582613f6e565b614c38565b82525050565b5f614c6b8287614be4565b601482019150614c7b8286614c04565b602082019150614c8b8285614c49565b600182019150614c9b8284614c04565b60208201915081905095945050505050565b5f81519050614cbb81613ffe565b92915050565b5f60208284031215614cd657614cd5613f66565b5b5f614ce384828501614cad565b91505092915050565b5f604082019050614cff5f830185614053565b614d0c60208301846140d9565b9392505050565b5f614d1d8261407b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d4f57614d4e61486d565b5b600182019050919050565b5f819050919050565b5f67ffffffffffffffff82169050919050565b5f614d90614d8b614d8684614d5a565b6149b7565b614d63565b9050919050565b614da081614d76565b82525050565b5f602082019050614db95f830184614d97565b92915050565b5f81519050614dcd816147eb565b92915050565b5f60208284031215614de857614de7613f66565b5b5f614df584828501614dbf565b91505092915050565b5f81905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f82015250565b5f614e3c601c83614dfe565b9150614e4782614e08565b601c82019050919050565b5f819050919050565b614e6c614e67826142d5565b614e52565b82525050565b5f614e7c82614e30565b9150614e888284614e5b565b60208201915081905092915050565b5f604082019050614eaa5f8301856140d9565b614eb760208301846140d9565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f81519050919050565b5f81905092915050565b5f614f0982614eeb565b614f138185614ef5565b9350614f238185602086016144ec565b80840191505092915050565b5f614f3a8284614eff565b915081905092915050565b5f60ff82169050919050565b614f5a81614f45565b82525050565b5f608082019050614f735f8301876142de565b614f806020830186614f51565b614f8d60408301856142de565b614f9a60608301846142de565b9594505050505056fea26469706673582212203ef92f74ae6d571a38f75a531fa7337d82fb2399eae3d01a91a8321a4caef8a664736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.