Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 16 from a total of 16 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Restore Reward E... | 20632209 | 15 days ago | IN | 0 ETH | 0.00004323 | ||||
Restore Reward E... | 20151998 | 82 days ago | IN | 0 ETH | 0.00007063 | ||||
Restore Reward E... | 19936709 | 112 days ago | IN | 0 ETH | 0.00021754 | ||||
Restore Reward E... | 19736265 | 140 days ago | IN | 0 ETH | 0.00022974 | ||||
Restore Reward E... | 19425739 | 184 days ago | IN | 0 ETH | 0.00242935 | ||||
Restore Reward E... | 19425738 | 184 days ago | IN | 0 ETH | 0.00247639 | ||||
Restore Reward E... | 19372138 | 191 days ago | IN | 0 ETH | 0.0025917 | ||||
Restore Reward E... | 19372137 | 191 days ago | IN | 0 ETH | 0.00264578 | ||||
Restore Reward E... | 19338125 | 196 days ago | IN | 0 ETH | 0.00182842 | ||||
Restore Reward E... | 19338125 | 196 days ago | IN | 0 ETH | 0.00182842 | ||||
Restore Reward E... | 19196388 | 216 days ago | IN | 0 ETH | 0.00127862 | ||||
Restore Reward E... | 18735157 | 280 days ago | IN | 0 ETH | 0.00231432 | ||||
Restore Reward E... | 18734829 | 281 days ago | IN | 0 ETH | 0.00161192 | ||||
Transfer Ownersh... | 15639522 | 714 days ago | IN | 0 ETH | 0.00051184 | ||||
Transfer Chaosne... | 15639480 | 715 days ago | IN | 0 ETH | 0.00059479 | ||||
0x60e06040 | 15639478 | 715 days ago | IN | 0 ETH | 0.05612047 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
SortitionPool
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.8.17; import "@thesis/solidity-contracts/contracts/token/IERC20WithPermit.sol"; import "@thesis/solidity-contracts/contracts/token/IReceiveApproval.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./RNG.sol"; import "./SortitionTree.sol"; import "./Rewards.sol"; import "./Chaosnet.sol"; /// @title Sortition Pool /// @notice A logarithmic data structure used to store the pool of eligible /// operators weighted by their stakes. It allows to select a group of operators /// based on the provided pseudo-random seed. contract SortitionPool is SortitionTree, Rewards, Ownable, Chaosnet, IReceiveApproval { using Branch for uint256; using Leaf for uint256; using Position for uint256; IERC20WithPermit public immutable rewardToken; uint256 public immutable poolWeightDivisor; bool public isLocked; event IneligibleForRewards(uint32[] ids, uint256 until); event RewardEligibilityRestored(address indexed operator, uint32 indexed id); /// @notice Reverts if called while pool is locked. modifier onlyUnlocked() { require(!isLocked, "Sortition pool locked"); _; } /// @notice Reverts if called while pool is unlocked. modifier onlyLocked() { require(isLocked, "Sortition pool unlocked"); _; } constructor(IERC20WithPermit _rewardToken, uint256 _poolWeightDivisor) { rewardToken = _rewardToken; poolWeightDivisor = _poolWeightDivisor; } function receiveApproval( address sender, uint256 amount, address token, bytes calldata ) external override { require(token == address(rewardToken), "Unsupported token"); rewardToken.transferFrom(sender, address(this), amount); Rewards.addRewards(uint96(amount), uint32(root.sumWeight())); } /// @notice Withdraws all available rewards for the given operator to the /// given beneficiary. /// @dev Can be called only be the owner. Does not validate if the provided /// beneficiary is associated with the provided operator - this needs to /// be done by the owner calling this function. /// @return The amount of rewards withdrawn in this call. function withdrawRewards(address operator, address beneficiary) public onlyOwner returns (uint96) { uint32 id = getOperatorID(operator); Rewards.updateOperatorRewards(id, uint32(getPoolWeight(operator))); uint96 earned = Rewards.withdrawOperatorRewards(id); rewardToken.transfer(beneficiary, uint256(earned)); return earned; } /// @notice Withdraws rewards not allocated to operators marked as ineligible /// to the given recipient address. /// @dev Can be called only by the owner. function withdrawIneligible(address recipient) public onlyOwner { uint96 earned = Rewards.withdrawIneligibleRewards(); rewardToken.transfer(recipient, uint256(earned)); } /// @notice Locks the sortition pool. In locked state, members cannot be /// inserted and removed from the pool. Members statuses cannot /// be updated as well. /// @dev Can be called only by the contract owner. function lock() public onlyOwner { isLocked = true; } /// @notice Unlocks the sortition pool. Removes all restrictions set by /// the `lock` method. /// @dev Can be called only by the contract owner. function unlock() public onlyOwner { isLocked = false; } /// @notice Inserts an operator to the pool. Reverts if the operator is /// already present. Reverts if the operator is not eligible because of their /// authorized stake. Reverts if the chaosnet is active and the operator is /// not a beta operator. /// @dev Can be called only by the contract owner. /// @param operator Address of the inserted operator. /// @param authorizedStake Inserted operator's authorized stake for the application. function insertOperator(address operator, uint256 authorizedStake) public onlyOwner onlyUnlocked { uint256 weight = getWeight(authorizedStake); require(weight > 0, "Operator not eligible"); if (isChaosnetActive) { require(isBetaOperator[operator], "Not beta operator for chaosnet"); } _insertOperator(operator, weight); uint32 id = getOperatorID(operator); Rewards.updateOperatorRewards(id, uint32(weight)); } /// @notice Update the operator's weight if present and eligible, /// or remove from the pool if present and ineligible. /// @dev Can be called only by the contract owner. /// @param operator Address of the updated operator. /// @param authorizedStake Operator's authorized stake for the application. function updateOperatorStatus(address operator, uint256 authorizedStake) public onlyOwner onlyUnlocked { uint256 weight = getWeight(authorizedStake); uint32 id = getOperatorID(operator); Rewards.updateOperatorRewards(id, uint32(weight)); if (weight == 0) { _removeOperator(operator); } else { updateOperator(operator, weight); } } /// @notice Set the given operators as ineligible for rewards. /// The operators can restore their eligibility at the given time. function setRewardIneligibility(uint32[] calldata operators, uint256 until) public onlyOwner { Rewards.setIneligible(operators, until); emit IneligibleForRewards(operators, until); } /// @notice Restores reward eligibility for the operator. function restoreRewardEligibility(address operator) public { uint32 id = getOperatorID(operator); Rewards.restoreEligibility(id); emit RewardEligibilityRestored(operator, id); } /// @notice Returns whether the operator is eligible for rewards or not. function isEligibleForRewards(address operator) public view returns (bool) { uint32 id = getOperatorID(operator); return Rewards.isEligibleForRewards(id); } /// @notice Returns the time the operator's reward eligibility can be restored. function rewardsEligibilityRestorableAt(address operator) public view returns (uint256) { uint32 id = getOperatorID(operator); return Rewards.rewardsEligibilityRestorableAt(id); } /// @notice Returns whether the operator is able to restore their eligibility /// for rewards right away. function canRestoreRewardEligibility(address operator) public view returns (bool) { uint32 id = getOperatorID(operator); return Rewards.canRestoreRewardEligibility(id); } /// @notice Returns the amount of rewards withdrawable for the given operator. function getAvailableRewards(address operator) public view returns (uint96) { uint32 id = getOperatorID(operator); return availableRewards(id); } /// @notice Return whether the operator is present in the pool. function isOperatorInPool(address operator) public view returns (bool) { return getFlaggedLeafPosition(operator) != 0; } /// @notice Return whether the operator's weight in the pool /// matches their eligible weight. function isOperatorUpToDate(address operator, uint256 authorizedStake) public view returns (bool) { return getWeight(authorizedStake) == getPoolWeight(operator); } /// @notice Return the weight of the operator in the pool, /// which may or may not be out of date. function getPoolWeight(address operator) public view returns (uint256) { uint256 flaggedPosition = getFlaggedLeafPosition(operator); if (flaggedPosition == 0) { return 0; } else { uint256 leafPosition = flaggedPosition.unsetFlag(); uint256 leafWeight = getLeafWeight(leafPosition); return leafWeight; } } /// @notice Selects a new group of operators of the provided size based on /// the provided pseudo-random seed. At least one operator has to be /// registered in the pool, otherwise the function fails reverting the /// transaction. /// @param groupSize Size of the requested group /// @param seed Pseudo-random number used to select operators to group /// @return selected Members of the selected group function selectGroup(uint256 groupSize, bytes32 seed) public view onlyLocked returns (uint32[] memory) { uint256 _root = root; bytes32 rngState = seed; uint256 rngRange = _root.sumWeight(); require(rngRange > 0, "Not enough operators in pool"); uint256 currentIndex; uint256 bits = RNG.bitsRequired(rngRange); uint32[] memory selected = new uint32[](groupSize); for (uint256 i = 0; i < groupSize; i++) { (currentIndex, rngState) = RNG.getIndex(rngRange, rngState, bits); uint256 leafPosition = pickWeightedLeaf(currentIndex, _root); uint256 leaf = leaves[leafPosition]; selected[i] = leaf.id(); } return selected; } function getWeight(uint256 authorization) internal view returns (uint256) { return authorization / poolWeightDivisor; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "./IApproveAndCall.sol"; /// @title IERC20WithPermit /// @notice Burnable ERC20 token with EIP2612 permit functionality. User can /// authorize a transfer of their token with a signature conforming /// EIP712 standard instead of an on-chain transaction from their /// address. Anyone can submit this signature on the user's behalf by /// calling the permit function, as specified in EIP2612 standard, /// paying gas fees, and possibly performing other actions in the same /// transaction. interface IERC20WithPermit is IERC20, IERC20Metadata, IApproveAndCall { /// @notice EIP2612 approval made with secp256k1 signature. /// Users can authorize a transfer of their tokens with a signature /// conforming EIP712 standard, rather than an on-chain transaction /// from their address. Anyone can submit this signature on the /// user's behalf by calling the permit function, paying gas fees, /// and possibly performing other actions in the same transaction. /// @dev The deadline argument can be set to `type(uint256).max to create /// permits that effectively never expire. function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /// @notice Destroys `amount` tokens from the caller. function burn(uint256 amount) external; /// @notice Destroys `amount` of tokens from `account`, deducting the amount /// from caller's allowance. function burnFrom(address account, uint256 amount) external; /// @notice Returns hash of EIP712 Domain struct with the token name as /// a signing domain and token contract as a verifying contract. /// Used to construct EIP2612 signature provided to `permit` /// function. /* solhint-disable-next-line func-name-mixedcase */ function DOMAIN_SEPARATOR() external view returns (bytes32); /// @notice Returns the current nonce for EIP2612 permission for the /// provided token owner for a replay protection. Used to construct /// EIP2612 signature provided to `permit` function. function nonce(address owner) external view returns (uint256); /// @notice Returns EIP2612 Permit message hash. Used to construct EIP2612 /// signature provided to `permit` function. /* solhint-disable-next-line func-name-mixedcase */ function PERMIT_TYPEHASH() external pure returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice An interface that should be implemented by contracts supporting /// `approveAndCall`/`receiveApproval` pattern. interface IReceiveApproval { /// @notice Receives approval to spend tokens. Called as a result of /// `approveAndCall` call on the token. function receiveApproval( address from, uint256 amount, address token, bytes calldata extraData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
pragma solidity 0.8.17; import "./Leaf.sol"; import "./Constants.sol"; library RNG { /// @notice Get an index in the range `[0 .. range-1]` /// and the new state of the RNG, /// using the provided `state` of the RNG. /// /// @param range The upper bound of the index, exclusive. /// /// @param state The previous state of the RNG. /// The initial state needs to be obtained /// from a trusted randomness oracle (the random beacon), /// or from a chain of earlier calls to `RNG.getIndex()` /// on an originally trusted seed. /// /// @dev Calculates the number of bits required for the desired range, /// takes the least significant bits of `state` /// and checks if the obtained index is within the desired range. /// The original state is hashed with `keccak256` to get a new state. /// If the index is outside the range, /// the function retries until it gets a suitable index. /// /// @return index A random integer between `0` and `range - 1`, inclusive. /// /// @return newState The new state of the RNG. /// When `getIndex()` is called one or more times, /// care must be taken to always use the output `state` /// of the most recent call as the input `state` of a subsequent call. /// At the end of a transaction calling `RNG.getIndex()`, /// the previous stored state must be overwritten with the latest output. function getIndex( uint256 range, bytes32 state, uint256 bits ) internal view returns (uint256, bytes32) { bool found = false; uint256 index = 0; bytes32 newState = state; while (!found) { index = truncate(bits, uint256(newState)); newState = keccak256(abi.encodePacked(newState, address(this))); if (index < range) { found = true; } } return (index, newState); } /// @notice Calculate how many bits are required /// for an index in the range `[0 .. range-1]`. /// /// @param range The upper bound of the desired range, exclusive. /// /// @return uint The smallest number of bits /// that can contain the number `range-1`. function bitsRequired(uint256 range) internal pure returns (uint256) { unchecked { if (range == 1) { return 0; } uint256 bits = Constants.WEIGHT_WIDTH - 1; // Left shift by `bits`, // so we have a 1 in the (bits + 1)th least significant bit // and 0 in other bits. // If this number is equal or greater than `range`, // the range [0, range-1] fits in `bits` bits. // // Because we loop from high bits to low bits, // we find the highest number of bits that doesn't fit the range, // and return that number + 1. while (1 << bits >= range) { bits--; } return bits + 1; } } /// @notice Truncate `input` to the `bits` least significant bits. function truncate(uint256 bits, uint256 input) internal pure returns (uint256) { unchecked { return input & ((1 << bits) - 1); } } }
pragma solidity 0.8.17; import "./Branch.sol"; import "./Position.sol"; import "./Leaf.sol"; import "./Constants.sol"; contract SortitionTree { using Branch for uint256; using Position for uint256; using Leaf for uint256; // implicit tree // root 8 // level2 64 // level3 512 // level4 4k // level5 32k // level6 256k // level7 2M uint256 internal root; // A 2-index mapping from layer => (index (0-index) => branch). For example, // to access the 6th branch in the 2nd layer (right below the root node; the // first branch layer), call branches[2][5]. Mappings are used in place of // arrays for efficiency. The root is the first layer, the branches occupy // layers 2 through 7, and layer 8 is for the leaves. Following this // convention, the first index in `branches` is `2`, and the last index is // `7`. mapping(uint256 => mapping(uint256 => uint256)) internal branches; // A 0-index mapping from index => leaf, acting as an array. For example, to // access the 42nd leaf, call leaves[41]. mapping(uint256 => uint256) internal leaves; // the flagged (see setFlag() and unsetFlag() in Position.sol) positions // of all operators present in the pool mapping(address => uint256) internal flaggedLeafPosition; // the leaf after the rightmost occupied leaf of each stack uint256 internal rightmostLeaf; // the empty leaves in each stack // between 0 and the rightmost occupied leaf uint256[] internal emptyLeaves; // Each operator has an uint32 ID number // which is allocated when they first join the pool // and remains unchanged even if they leave and rejoin the pool. mapping(address => uint32) internal operatorID; // The idAddress array records the address corresponding to each ID number. // The ID number 0 is initialized with a zero address and is not used. address[] internal idAddress; constructor() { root = 0; rightmostLeaf = 0; idAddress.push(); } /// @notice Return the ID number of the given operator address. An ID number /// of 0 means the operator has not been allocated an ID number yet. /// @param operator Address of the operator. /// @return the ID number of the given operator address function getOperatorID(address operator) public view returns (uint32) { return operatorID[operator]; } /// @notice Get the operator address corresponding to the given ID number. A /// zero address means the ID number has not been allocated yet. /// @param id ID of the operator /// @return the address of the operator function getIDOperator(uint32 id) public view returns (address) { return idAddress.length > id ? idAddress[id] : address(0); } /// @notice Gets the operator addresses corresponding to the given ID /// numbers. A zero address means the ID number has not been allocated yet. /// This function works just like getIDOperator except that it allows to fetch /// operator addresses for multiple IDs in one call. /// @param ids the array of the operator ids /// @return an array of the associated operator addresses function getIDOperators(uint32[] calldata ids) public view returns (address[] memory) { uint256 idCount = idAddress.length; address[] memory operators = new address[](ids.length); for (uint256 i = 0; i < ids.length; i++) { uint32 id = ids[i]; operators[i] = idCount > id ? idAddress[id] : address(0); } return operators; } /// @notice Checks if operator is already registered in the pool. /// @param operator the address of the operator /// @return whether or not the operator is already registered in the pool function isOperatorRegistered(address operator) public view returns (bool) { return getFlaggedLeafPosition(operator) != 0; } /// @notice Sum the number of operators in each trunk. /// @return the number of operators in the pool function operatorsInPool() public view returns (uint256) { // Get the number of leaves that might be occupied; // if `rightmostLeaf` equals `firstLeaf()` the tree must be empty, // otherwise the difference between these numbers // gives the number of leaves that may be occupied. uint256 nPossiblyUsedLeaves = rightmostLeaf; // Get the number of empty leaves // not accounted for by the `rightmostLeaf` uint256 nEmptyLeaves = emptyLeaves.length; return (nPossiblyUsedLeaves - nEmptyLeaves); } /// @notice Convenience method to return the total weight of the pool /// @return the total weight of the pool function totalWeight() public view returns (uint256) { return root.sumWeight(); } /// @notice Give the operator a new ID number. /// Does not check if the operator already has an ID number. /// @param operator the address of the operator /// @return a new ID for that operator function allocateOperatorID(address operator) internal returns (uint256) { uint256 id = idAddress.length; require(id <= type(uint32).max, "Pool capacity exceeded"); operatorID[operator] = uint32(id); idAddress.push(operator); return id; } /// @notice Inserts an operator into the sortition pool /// @param operator the address of an operator to insert /// @param weight how much weight that operator has in the pool function _insertOperator(address operator, uint256 weight) internal { require( !isOperatorRegistered(operator), "Operator is already registered in the pool" ); // Fetch the operator's ID, and if they don't have one, allocate them one. uint256 id = getOperatorID(operator); if (id == 0) { id = allocateOperatorID(operator); } // Determine which leaf to insert them into uint256 position = getEmptyLeafPosition(); // Record the block the operator was inserted in uint256 theLeaf = Leaf.make(operator, block.number, id); // Update the leaf, and propagate the weight changes all the way up to the // root. root = setLeaf(position, theLeaf, weight, root); // Without position flags, // the position 0x000000 would be treated as empty flaggedLeafPosition[operator] = position.setFlag(); } /// @notice Remove an operator (and their weight) from the pool. /// @param operator the address of the operator to remove function _removeOperator(address operator) internal { uint256 flaggedPosition = getFlaggedLeafPosition(operator); require(flaggedPosition != 0, "Operator is not registered in the pool"); uint256 unflaggedPosition = flaggedPosition.unsetFlag(); // Update the leaf, and propagate the weight changes all the way up to the // root. root = removeLeaf(unflaggedPosition, root); removeLeafPositionRecord(operator); } /// @notice Update an operator's weight in the pool. /// @param operator the address of the operator to update /// @param weight the new weight function updateOperator(address operator, uint256 weight) internal { require( isOperatorRegistered(operator), "Operator is not registered in the pool" ); uint256 flaggedPosition = getFlaggedLeafPosition(operator); uint256 unflaggedPosition = flaggedPosition.unsetFlag(); root = updateLeaf(unflaggedPosition, weight, root); } /// @notice Helper method to remove a leaf position record for an operator. /// @param operator the address of the operator to remove the record for function removeLeafPositionRecord(address operator) internal { flaggedLeafPosition[operator] = 0; } /// @notice Removes the data and weight from a particular leaf. /// @param position the leaf index to remove /// @param _root the root node containing the leaf /// @return the updated root node function removeLeaf(uint256 position, uint256 _root) internal returns (uint256) { uint256 rightmostSubOne = rightmostLeaf - 1; bool isRightmost = position == rightmostSubOne; // Clears out the data in the leaf node, and then propagates the weight // changes all the way up to the root. uint256 newRoot = setLeaf(position, 0, 0, _root); // Infer if need to fall back on emptyLeaves yet if (isRightmost) { rightmostLeaf = rightmostSubOne; } else { emptyLeaves.push(position); } return newRoot; } /// @notice Updates the tree to give a particular leaf a new weight. /// @param position the index of the leaf to update /// @param weight the new weight /// @param _root the root node containing the leaf /// @return the updated root node function updateLeaf( uint256 position, uint256 weight, uint256 _root ) internal returns (uint256) { if (getLeafWeight(position) != weight) { return updateTree(position, weight, _root); } else { return _root; } } /// @notice Places a leaf into a particular position, with a given weight and /// propagates that change. /// @param position the index to place the leaf in /// @param theLeaf the new leaf to place in the position /// @param leafWeight the weight of the leaf /// @param _root the root containing the new leaf /// @return the updated root node function setLeaf( uint256 position, uint256 theLeaf, uint256 leafWeight, uint256 _root ) internal returns (uint256) { // set leaf leaves[position] = theLeaf; return (updateTree(position, leafWeight, _root)); } /// @notice Propagates a weight change at a position through the tree, /// eventually returning the updated root. /// @param position the index of leaf to update /// @param weight the new weight of the leaf /// @param _root the root node containing the leaf /// @return the updated root node function updateTree( uint256 position, uint256 weight, uint256 _root ) internal returns (uint256) { uint256 childSlot; uint256 treeNode; uint256 newNode; uint256 nodeWeight = weight; uint256 parent = position; // set levels 7 to 2 for (uint256 level = Constants.LEVELS; level >= 2; level--) { childSlot = parent.slot(); parent = parent.parent(); treeNode = branches[level][parent]; newNode = treeNode.setSlot(childSlot, nodeWeight); branches[level][parent] = newNode; nodeWeight = newNode.sumWeight(); } // set level Root childSlot = parent.slot(); return _root.setSlot(childSlot, nodeWeight); } /// @notice Retrieves the next available empty leaf position. Tries to fill /// left to right first, ignoring leaf removals, and then fills /// most-recent-removals first. /// @return the position of the empty leaf function getEmptyLeafPosition() internal returns (uint256) { uint256 rLeaf = rightmostLeaf; bool spaceOnRight = (rLeaf + 1) < Constants.POOL_CAPACITY; if (spaceOnRight) { rightmostLeaf = rLeaf + 1; return rLeaf; } else { uint256 emptyLeafCount = emptyLeaves.length; require(emptyLeafCount > 0, "Pool is full"); uint256 emptyLeaf = emptyLeaves[emptyLeafCount - 1]; emptyLeaves.pop(); return emptyLeaf; } } /// @notice Gets the flagged leaf position for an operator. /// @param operator the address of the operator /// @return the leaf position of that operator function getFlaggedLeafPosition(address operator) internal view returns (uint256) { return flaggedLeafPosition[operator]; } /// @notice Gets the weight of a leaf at a particular position. /// @param position the index of the leaf /// @return the weight of the leaf at that position function getLeafWeight(uint256 position) internal view returns (uint256) { uint256 slot = position.slot(); uint256 parent = position.parent(); // A leaf's weight information is stored a 32-bit slot in the branch layer // directly above the leaf layer. To access it, we calculate that slot and // parent position, and always know the hard-coded layer index. uint256 node = branches[Constants.LEVELS][parent]; return node.getSlot(slot); } /// @notice Picks a leaf given a random index. /// @param index a number in `[0, _root.totalWeight())` used to decide /// between leaves /// @param _root the root of the tree function pickWeightedLeaf(uint256 index, uint256 _root) internal view returns (uint256 leafPosition) { uint256 currentIndex = index; uint256 currentNode = _root; uint256 currentPosition = 0; uint256 currentSlot; require(index < currentNode.sumWeight(), "Index exceeds weight"); // get root slot (currentSlot, currentIndex) = currentNode.pickWeightedSlot(currentIndex); // get slots from levels 2 to 7 for (uint256 level = 2; level <= Constants.LEVELS; level++) { currentPosition = currentPosition.child(currentSlot); currentNode = branches[level][currentPosition]; (currentSlot, currentIndex) = currentNode.pickWeightedSlot(currentIndex); } // get leaf position leafPosition = currentPosition.child(currentSlot); } }
pragma solidity 0.8.17; /// @title Rewards /// @notice Rewards are allocated proportionally to operators /// present in the pool at payout based on their weight in the pool. /// /// To facilitate this, we use a global accumulator value /// to track the total rewards one unit of weight would've earned /// since the creation of the pool. /// /// Whenever a reward is paid, the accumulator is increased /// by the size of the reward divided by the total weight /// of all eligible operators in the pool. /// /// Each operator has an individual accumulator value, /// set to equal the global accumulator when the operator joins the pool. /// This accumulator reflects the amount of rewards /// that have already been accounted for with that operator. /// /// Whenever an operator's weight in the pool changes, /// we can update the amount of rewards the operator has earned /// by subtracting the operator's accumulator from the global accumulator. /// This gives us the amount of rewards one unit of weight has earned /// since the last time the operator's rewards have been updated. /// Then we multiply that by the operator's previous (pre-change) weight /// to determine how much rewards in total the operator has earned, /// and add this to the operator's earned rewards. /// Finally, we set the operator's accumulator to the global accumulator value. contract Rewards { struct OperatorRewards { // The state of the global accumulator // when the operator's rewards were last updated uint96 accumulated; // The amount of rewards collected by the operator after the latest update. // The amount the operator could withdraw may equal `available` // or it may be greater, if more rewards have been paid in since then. // To evaulate the most recent amount including rewards potentially paid // since the last update, use `availableRewards` function. uint96 available; // If nonzero, the operator is ineligible for rewards // and may only re-enable rewards after the specified timestamp. // XXX: unsigned 32-bit integer unix seconds, will break around 2106 uint32 ineligibleUntil; // Locally cached weight of the operator, // used to reduce the cost of setting operators ineligible. uint32 weight; } // The global accumulator of how much rewards // a hypothetical operator of weight 1 would have earned // since the creation of the pool. uint96 internal globalRewardAccumulator; // If the amount of reward tokens paid in // does not divide cleanly by pool weight, // the difference is recorded as rounding dust // and added to the next reward. uint96 internal rewardRoundingDust; // The amount of rewards that would've been earned by ineligible operators // had they not been ineligible. uint96 public ineligibleEarnedRewards; // Ineligibility times are calculated from this offset, // set at contract creation. uint256 internal immutable ineligibleOffsetStart; mapping(uint32 => OperatorRewards) internal operatorRewards; constructor() { // solhint-disable-next-line not-rely-on-time ineligibleOffsetStart = block.timestamp; } /// @notice Return whether the operator is eligible for rewards or not. function isEligibleForRewards(uint32 operator) internal view returns (bool) { return operatorRewards[operator].ineligibleUntil == 0; } /// @notice Return the time the operator's reward eligibility can be restored. function rewardsEligibilityRestorableAt(uint32 operator) internal view returns (uint256) { uint32 until = operatorRewards[operator].ineligibleUntil; require(until != 0, "Operator already eligible"); return (uint256(until) + ineligibleOffsetStart); } /// @notice Return whether the operator is able to restore their eligibility /// for rewards right away. function canRestoreRewardEligibility(uint32 operator) internal view returns (bool) { // solhint-disable-next-line not-rely-on-time return rewardsEligibilityRestorableAt(operator) <= block.timestamp; } /// @notice Internal function for updating the global state of rewards. function addRewards(uint96 rewardAmount, uint32 currentPoolWeight) internal { require(currentPoolWeight > 0, "No recipients in pool"); uint96 totalAmount = rewardAmount + rewardRoundingDust; uint96 perWeightReward = totalAmount / currentPoolWeight; uint96 newRoundingDust = totalAmount % currentPoolWeight; globalRewardAccumulator += perWeightReward; rewardRoundingDust = newRoundingDust; } /// @notice Internal function for updating the operator's reward state. function updateOperatorRewards(uint32 operator, uint32 newWeight) internal { uint96 acc = globalRewardAccumulator; OperatorRewards memory o = operatorRewards[operator]; uint96 accruedRewards = (acc - o.accumulated) * uint96(o.weight); if (o.ineligibleUntil == 0) { // If operator is not ineligible, update their earned rewards o.available += accruedRewards; } else { // If ineligible, put the rewards into the ineligible pot ineligibleEarnedRewards += accruedRewards; } // In any case, update their accumulator and weight o.accumulated = acc; o.weight = newWeight; operatorRewards[operator] = o; } /// @notice Set the amount of withdrawable tokens to zero /// and return the previous withdrawable amount. /// @dev Does not update the withdrawable amount, /// but should usually be accompanied by an update. function withdrawOperatorRewards(uint32 operator) internal returns (uint96 withdrawable) { OperatorRewards storage o = operatorRewards[operator]; withdrawable = o.available; o.available = 0; } /// @notice Set the amount of ineligible-earned tokens to zero /// and return the previous amount. function withdrawIneligibleRewards() internal returns (uint96 withdrawable) { withdrawable = ineligibleEarnedRewards; ineligibleEarnedRewards = 0; } /// @notice Set the given operators as ineligible for rewards. /// The operators can restore their eligibility at the given time. function setIneligible(uint32[] memory operators, uint256 until) internal { OperatorRewards memory o = OperatorRewards(0, 0, 0, 0); uint96 globalAcc = globalRewardAccumulator; uint96 accrued = 0; // Record ineligibility as seconds after contract creation uint32 _until = uint32(until - ineligibleOffsetStart); for (uint256 i = 0; i < operators.length; i++) { uint32 operator = operators[i]; OperatorRewards storage r = operatorRewards[operator]; o.available = r.available; o.accumulated = r.accumulated; o.ineligibleUntil = r.ineligibleUntil; o.weight = r.weight; if (o.ineligibleUntil != 0) { // If operator is already ineligible, // don't earn rewards or shorten its ineligibility if (o.ineligibleUntil < _until) { o.ineligibleUntil = _until; } } else { // The operator becomes ineligible -> earn rewards o.ineligibleUntil = _until; accrued = (globalAcc - o.accumulated) * uint96(o.weight); o.available += accrued; } o.accumulated = globalAcc; r.available = o.available; r.accumulated = o.accumulated; r.ineligibleUntil = o.ineligibleUntil; r.weight = o.weight; } } /// @notice Restore the given operator's eligibility for rewards. function restoreEligibility(uint32 operator) internal { // solhint-disable-next-line not-rely-on-time require(canRestoreRewardEligibility(operator), "Operator still ineligible"); uint96 acc = globalRewardAccumulator; OperatorRewards memory o = operatorRewards[operator]; uint96 accruedRewards = (acc - o.accumulated) * uint96(o.weight); ineligibleEarnedRewards += accruedRewards; o.accumulated = acc; o.ineligibleUntil = 0; operatorRewards[operator] = o; } /// @notice Returns the amount of rewards currently available for withdrawal /// for the given operator. function availableRewards(uint32 operator) internal view returns (uint96) { uint96 acc = globalRewardAccumulator; OperatorRewards memory o = operatorRewards[operator]; if (o.ineligibleUntil == 0) { // If operator is not ineligible, calculate newly accrued rewards and add // them to the available ones, calculated during the last update. uint96 accruedRewards = (acc - o.accumulated) * uint96(o.weight); return o.available + accruedRewards; } else { // If ineligible, return only the rewards calculated during the last // update. return o.available; } } }
pragma solidity 0.8.17; /// @title Chaosnet /// @notice This is a beta staker program for stakers willing to go the extra /// mile with monitoring, share their logs with the dev team, and allow to more /// carefully monitor the bootstrapping network. As the network matures, the /// beta program will be ended. contract Chaosnet { /// @notice Indicates if the chaosnet is active. The chaosnet is active /// after the contract deployment and can be ended with a call to /// `deactivateChaosnet()`. Once deactivated chaosnet can not be activated /// again. bool public isChaosnetActive; /// @notice Indicates if the given operator is a beta operator for chaosnet. mapping(address => bool) public isBetaOperator; /// @notice Address controlling chaosnet status and beta operator addresses. address public chaosnetOwner; event BetaOperatorsAdded(address[] operators); event ChaosnetOwnerRoleTransferred( address oldChaosnetOwner, address newChaosnetOwner ); event ChaosnetDeactivated(); constructor() { _transferChaosnetOwner(msg.sender); isChaosnetActive = true; } modifier onlyChaosnetOwner() { require(msg.sender == chaosnetOwner, "Not the chaosnet owner"); _; } modifier onlyOnChaosnet() { require(isChaosnetActive, "Chaosnet is not active"); _; } /// @notice Adds beta operator to chaosnet. Can be called only by the /// chaosnet owner when the chaosnet is active. Once the operator is added /// as a beta operator, it can not be removed. function addBetaOperators(address[] calldata operators) public onlyOnChaosnet onlyChaosnetOwner { for (uint256 i = 0; i < operators.length; i++) { isBetaOperator[operators[i]] = true; } emit BetaOperatorsAdded(operators); } /// @notice Deactivates the chaosnet. Can be called only by the chaosnet /// owner. Once deactivated chaosnet can not be activated again. function deactivateChaosnet() public onlyOnChaosnet onlyChaosnetOwner { isChaosnetActive = false; emit ChaosnetDeactivated(); } /// @notice Transfers the chaosnet owner role to another non-zero address. function transferChaosnetOwnerRole(address newChaosnetOwner) public onlyChaosnetOwner { require( newChaosnetOwner != address(0), "New chaosnet owner must not be zero address" ); _transferChaosnetOwner(newChaosnetOwner); } function _transferChaosnetOwner(address newChaosnetOwner) internal { address oldChaosnetOwner = chaosnetOwner; chaosnetOwner = newChaosnetOwner; emit ChaosnetOwnerRoleTransferred(oldChaosnetOwner, newChaosnetOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice An interface that should be implemented by tokens supporting /// `approveAndCall`/`receiveApproval` pattern. interface IApproveAndCall { /// @notice Executes `receiveApproval` function on spender as specified in /// `IReceiveApproval` interface. Approves spender to withdraw from /// the caller multiple times, up to the `amount`. If this /// function is called again, it overwrites the current allowance /// with `amount`. Reverts if the approval reverted or if /// `receiveApproval` call on the spender reverted. function approveAndCall( address spender, uint256 amount, bytes memory extraData ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
pragma solidity 0.8.17; import "./Constants.sol"; library Leaf { function make( address _operator, uint256 _creationBlock, uint256 _id ) internal pure returns (uint256) { assert(_creationBlock <= type(uint64).max); assert(_id <= type(uint32).max); // Converting a bytesX type into a larger type // adds zero bytes on the right. uint256 op = uint256(bytes32(bytes20(_operator))); // Bitwise AND the id to erase // all but the 32 least significant bits uint256 uid = _id & Constants.ID_MAX; // Erase all but the 64 least significant bits, // then shift left by 32 bits to make room for the id uint256 cb = (_creationBlock & Constants.BLOCKHEIGHT_MAX) << Constants.ID_WIDTH; // Bitwise OR them all together to get // [address operator || uint64 creationBlock || uint32 id] return (op | cb | uid); } function operator(uint256 leaf) internal pure returns (address) { // Converting a bytesX type into a smaller type // truncates it on the right. return address(bytes20(bytes32(leaf))); } /// @notice Return the block number the leaf was created in. function creationBlock(uint256 leaf) internal pure returns (uint256) { return ((leaf >> Constants.ID_WIDTH) & Constants.BLOCKHEIGHT_MAX); } function id(uint256 leaf) internal pure returns (uint32) { // Id is stored in the 32 least significant bits. // Bitwise AND ensures that we only get the contents of those bits. return uint32(leaf & Constants.ID_MAX); } }
pragma solidity 0.8.17; library Constants { //////////////////////////////////////////////////////////////////////////// // Parameters for configuration // How many bits a position uses per level of the tree; // each branch of the tree contains 2**SLOT_BITS slots. uint256 constant SLOT_BITS = 3; uint256 constant LEVELS = 7; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Derived constants, do not touch uint256 constant SLOT_COUNT = 2**SLOT_BITS; uint256 constant SLOT_WIDTH = 256 / SLOT_COUNT; uint256 constant LAST_SLOT = SLOT_COUNT - 1; uint256 constant SLOT_MAX = (2**SLOT_WIDTH) - 1; uint256 constant POOL_CAPACITY = SLOT_COUNT**LEVELS; uint256 constant ID_WIDTH = SLOT_WIDTH; uint256 constant ID_MAX = SLOT_MAX; uint256 constant BLOCKHEIGHT_WIDTH = 96 - ID_WIDTH; uint256 constant BLOCKHEIGHT_MAX = (2**BLOCKHEIGHT_WIDTH) - 1; uint256 constant SLOT_POINTER_MAX = (2**SLOT_BITS) - 1; uint256 constant LEAF_FLAG = 1 << 255; uint256 constant WEIGHT_WIDTH = 256 / SLOT_COUNT; //////////////////////////////////////////////////////////////////////////// }
pragma solidity 0.8.17; import "./Constants.sol"; /// @notice The implicit 8-ary trees of the sortition pool /// rely on packing 8 "slots" of 32-bit values into each uint256. /// The Branch library permits efficient calculations on these slots. library Branch { /// @notice Calculate the right shift required /// to make the 32 least significant bits of an uint256 /// be the bits of the `position`th slot /// when treating the uint256 as a uint32[8]. /// /// @dev Not used for efficiency reasons, /// but left to illustrate the meaning of a common pattern. /// I wish solidity had macros, even C macros. function slotShift(uint256 position) internal pure returns (uint256) { unchecked { return position * Constants.SLOT_WIDTH; } } /// @notice Return the `position`th slot of the `node`, /// treating `node` as a uint32[32]. function getSlot(uint256 node, uint256 position) internal pure returns (uint256) { unchecked { uint256 shiftBits = position * Constants.SLOT_WIDTH; // Doing a bitwise AND with `SLOT_MAX` // clears all but the 32 least significant bits. // Because of the right shift by `slotShift(position)` bits, // those 32 bits contain the 32 bits in the `position`th slot of `node`. return (node >> shiftBits) & Constants.SLOT_MAX; } } /// @notice Return `node` with the `position`th slot set to zero. function clearSlot(uint256 node, uint256 position) internal pure returns (uint256) { unchecked { uint256 shiftBits = position * Constants.SLOT_WIDTH; // Shifting `SLOT_MAX` left by `slotShift(position)` bits // gives us a number where all bits of the `position`th slot are set, // and all other bits are unset. // // Using a bitwise NOT on this number, // we get a uint256 where all bits are set // except for those of the `position`th slot. // // Bitwise ANDing the original `node` with this number // sets the bits of `position`th slot to zero, // leaving all other bits unchanged. return node & ~(Constants.SLOT_MAX << shiftBits); } } /// @notice Return `node` with the `position`th slot set to `weight`. /// /// @param weight The weight of of the node. /// Safely truncated to a 32-bit number, /// but this should never be called with an overflowing weight regardless. function setSlot( uint256 node, uint256 position, uint256 weight ) internal pure returns (uint256) { unchecked { uint256 shiftBits = position * Constants.SLOT_WIDTH; // Clear the `position`th slot like in `clearSlot()`. uint256 clearedNode = node & ~(Constants.SLOT_MAX << shiftBits); // Bitwise AND `weight` with `SLOT_MAX` // to clear all but the 32 least significant bits. // // Shift this left by `slotShift(position)` bits // to obtain a uint256 with all bits unset // except in the `position`th slot // which contains the 32-bit value of `weight`. uint256 shiftedWeight = (weight & Constants.SLOT_MAX) << shiftBits; // When we bitwise OR these together, // all other slots except the `position`th one come from the left argument, // and the `position`th gets filled with `weight` from the right argument. return clearedNode | shiftedWeight; } } /// @notice Calculate the summed weight of all slots in the `node`. function sumWeight(uint256 node) internal pure returns (uint256 sum) { unchecked { sum = node & Constants.SLOT_MAX; // Iterate through each slot // by shifting `node` right in increments of 32 bits, // and adding the 32 least significant bits to the `sum`. uint256 newNode = node >> Constants.SLOT_WIDTH; while (newNode > 0) { sum += (newNode & Constants.SLOT_MAX); newNode = newNode >> Constants.SLOT_WIDTH; } return sum; } } /// @notice Pick a slot in `node` that corresponds to `index`. /// Treats the node like an array of virtual stakers, /// the number of virtual stakers in each slot corresponding to its weight, /// and picks which slot contains the `index`th virtual staker. /// /// @dev Requires that `index` be lower than `sumWeight(node)`. /// However, this is not enforced for performance reasons. /// If `index` exceeds the permitted range, /// `pickWeightedSlot()` returns the rightmost slot /// and an excessively high `newIndex`. /// /// @return slot The slot of `node` containing the `index`th virtual staker. /// /// @return newIndex The index of the `index`th virtual staker of `node` /// within the returned slot. function pickWeightedSlot(uint256 node, uint256 index) internal pure returns (uint256 slot, uint256 newIndex) { unchecked { newIndex = index; uint256 newNode = node; uint256 currentSlotWeight = newNode & Constants.SLOT_MAX; while (newIndex >= currentSlotWeight) { newIndex -= currentSlotWeight; slot++; newNode = newNode >> Constants.SLOT_WIDTH; currentSlotWeight = newNode & Constants.SLOT_MAX; } return (slot, newIndex); } } }
pragma solidity 0.8.17; import "./Constants.sol"; library Position { // Return the last 3 bits of a position number, // corresponding to its slot in its parent function slot(uint256 a) internal pure returns (uint256) { return a & Constants.SLOT_POINTER_MAX; } // Return the parent of a position number function parent(uint256 a) internal pure returns (uint256) { return a >> Constants.SLOT_BITS; } // Return the location of the child of a at the given slot function child(uint256 a, uint256 s) internal pure returns (uint256) { return (a << Constants.SLOT_BITS) | (s & Constants.SLOT_POINTER_MAX); // slot(s) } // Return the uint p as a flagged position uint: // the least significant 21 bits contain the position // and the 22nd bit is set as a flag // to distinguish the position 0x000000 from an empty field. function setFlag(uint256 p) internal pure returns (uint256) { return p | Constants.LEAF_FLAG; } // Turn a flagged position into an unflagged position // by removing the flag at the 22nd least significant bit. // // We shouldn't _actually_ need this // as all position-manipulating code should ignore non-position bits anyway // but it's cheap to call so might as well do it. function unsetFlag(uint256 p) internal pure returns (uint256) { return p & (~Constants.LEAF_FLAG); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC20WithPermit","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_poolWeightDivisor","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"operators","type":"address[]"}],"name":"BetaOperatorsAdded","type":"event"},{"anonymous":false,"inputs":[],"name":"ChaosnetDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldChaosnetOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newChaosnetOwner","type":"address"}],"name":"ChaosnetOwnerRoleTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32[]","name":"ids","type":"uint32[]"},{"indexed":false,"internalType":"uint256","name":"until","type":"uint256"}],"name":"IneligibleForRewards","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":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint32","name":"id","type":"uint32"}],"name":"RewardEligibilityRestored","type":"event"},{"inputs":[{"internalType":"address[]","name":"operators","type":"address[]"}],"name":"addBetaOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"canRestoreRewardEligibility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chaosnetOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deactivateChaosnet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getAvailableRewards","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"id","type":"uint32"}],"name":"getIDOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"ids","type":"uint32[]"}],"name":"getIDOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getOperatorID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getPoolWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ineligibleEarnedRewards","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"authorizedStake","type":"uint256"}],"name":"insertOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBetaOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isChaosnetActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isEligibleForRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorInPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"authorizedStake","type":"uint256"}],"name":"isOperatorUpToDate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operatorsInPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolWeightDivisor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"receiveApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"restoreRewardEligibility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20WithPermit","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"rewardsEligibilityRestorableAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupSize","type":"uint256"},{"internalType":"bytes32","name":"seed","type":"bytes32"}],"name":"selectGroup","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"operators","type":"uint32[]"},{"internalType":"uint256","name":"until","type":"uint256"}],"name":"setRewardIneligibility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newChaosnetOwner","type":"address"}],"name":"transferChaosnetOwnerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"authorizedStake","type":"uint256"}],"name":"updateOperatorStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawIneligible","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"beneficiary","type":"address"}],"name":"withdrawRewards","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162002c7138038062002c71833981016040819052620000349162000140565b6000808055600481905560078054600101815590524260805262000058336200008d565b6200006333620000df565b600b805460ff60a01b1916600160a01b1790556001600160a01b0390911660a05260c0526200017c565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600d80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527ff7d2871c195d5dcbeca7c9bfb4f7ae4149d0915a5d3d03c8c2286c9a24e932be910160405180910390a15050565b600080604083850312156200015457600080fd5b82516001600160a01b03811681146200016c57600080fd5b6020939093015192949293505050565b60805160a05160c051612a9b620001d6600039600081816102a6015261139001526000818161050101528181610ac801528181610b6701528181610cfb0152610fb10152600081816113040152611aa50152612a9b6000f3fe608060405234801561001057600080fd5b506004361061021b5760003560e01c806396c82e5711610125578063dc7520c5116100ad578063f2fde38b1161007c578063f2fde38b146104e9578063f7186ce014610329578063f7c618c1146104fc578063f7f9a8fa14610523578063f83d08ba1461054357600080fd5b8063dc7520c5146104b3578063e20981ca146104c6578063e7bfd899146104d9578063f23baf4a146104e157600080fd5b8063a9649414116100f4578063a964941414610453578063b0f3828e14610466578063b2f3db4d1461047a578063c0a3f9eb1461048d578063c545b3a9146104a057600080fd5b806396c82e571461041c578063a4e2d63414610424578063a69df4b514610438578063a7a7d3911461044057600080fd5b80636b1906f8116101a8578063873e31fa11610177578063873e31fa146103a75780638871ca5d146103d25780638da5cb5b146103e55780638f4ffcb1146103f6578063942f68921461040957600080fd5b80636b1906f8146103295780636c2530b914610354578063715018a6146103745780637c2cf6cd1461037c57600080fd5b806343a3db30116101ef57806343a3db30146102a15780634de824f0146102c85780635757ed5b146102db5780635a48b46b146102ee578063660186e61461031657600080fd5b8062983b7314610220578063241a418814610246578063398ece9c1461025b5780633e723fc91461028e575b600080fd5b61023361022e3660046123d2565b61054b565b6040519081526020015b60405180910390f35b6102596102543660046123ed565b610569565b005b61027e6102693660046123d2565b600c6020526000908152604090205460ff1681565b604051901515815260200161023d565b61025961029c36600461245c565b6106be565b6102337f000000000000000000000000000000000000000000000000000000000000000081565b61027e6102d63660046123ed565b6107ea565b6102336102e93660046123d2565b610808565b6103016102fc3660046123d2565b610856565b60405163ffffffff909116815260200161023d565b61027e6103243660046123d2565b610877565b61027e6103373660046123d2565b6001600160a01b0316600090815260036020526040902054151590565b61036761036236600461249e565b6108ac565b60405161023d91906124c0565b610259610a4e565b600d5461038f906001600160a01b031681565b6040516001600160a01b03909116815260200161023d565b6103ba6103b53660046123d2565b610a62565b6040516001600160601b03909116815260200161023d565b61038f6103e036600461251e565b610a79565b600b546001600160a01b031661038f565b610259610404366004612539565b610ac6565b6102596104173660046125d4565b610bf0565b610233610c76565b600d5461027e90600160a01b900460ff1681565b610259610c88565b6009546103ba906001600160601b031681565b6102596104613660046123d2565b610c9f565b600b5461027e90600160a01b900460ff1681565b6102596104883660046123d2565b610d6f565b61027e61049b3660046123d2565b610dc5565b6102596104ae3660046123d2565b610ddc565b6102596104c13660046123ed565b610e7c565b6103ba6104d4366004612620565b610f1a565b610233611029565b610259611044565b6102596104f73660046123d2565b6110f8565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b61053661053136600461245c565b61116e565b60405161023d9190612653565b610259611271565b60008061055783610856565b90506105628161128e565b9392505050565b61057161132f565b600d54600160a01b900460ff16156105c85760405162461bcd60e51b815260206004820152601560248201527414dbdc9d1a5d1a5bdb881c1bdbdb081b1bd8dad959605a1b60448201526064015b60405180910390fd5b60006105d382611389565b90506000811161061d5760405162461bcd60e51b81526020600482015260156024820152744f70657261746f72206e6f7420656c696769626c6560581b60448201526064016105bf565b600b54600160a01b900460ff1615610697576001600160a01b0383166000908152600c602052604090205460ff166106975760405162461bcd60e51b815260206004820152601e60248201527f4e6f742062657461206f70657261746f7220666f72206368616f736e6574000060448201526064016105bf565b6106a183826113b5565b60006106ac84610856565b90506106b881836114ab565b50505050565b600b54600160a01b900460ff166107105760405162461bcd60e51b81526020600482015260166024820152754368616f736e6574206973206e6f742061637469766560501b60448201526064016105bf565b600d546001600160a01b0316331461073a5760405162461bcd60e51b81526004016105bf90612694565b60005b818110156107ac576001600c600085858581811061075d5761075d6126c4565b905060200201602081019061077291906123d2565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806107a4816126f0565b91505061073d565b507f79b60dc9f29a0514f5ce9bf1e89b7add7a22440cde3b203c03a842e3b534071b82826040516107de929190612709565b60405180910390a15050565b60006107f583610808565b6107fe83611389565b1490505b92915050565b6001600160a01b038116600090815260036020526040812054806000036108325750600092915050565b6001600160ff1b038116600061084782611631565b95945050505050565b50919050565b6001600160a01b031660009081526006602052604090205463ffffffff1690565b60008061088383610856565b90506105628163ffffffff9081166000908152600a6020526040902054600160c01b9004161590565b600d54606090600160a01b900460ff166109085760405162461bcd60e51b815260206004820152601760248201527f536f72746974696f6e20706f6f6c20756e6c6f636b656400000000000000000060448201526064016105bf565b600080549083906109188361168e565b90506000811161096a5760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768206f70657261746f727320696e20706f6f6c0000000060448201526064016105bf565b600080610976836116b5565b905060008867ffffffffffffffff81111561099357610993612755565b6040519080825280602002602001820160405280156109bc578160200160208202803683370190505b50905060005b89811015610a41576109d58587856116e7565b9650935060006109e5858961175f565b600081815260026020526040902054909150610a008161182a565b848481518110610a1257610a126126c4565b602002602001019063ffffffff16908163ffffffff168152505050508080610a39906126f0565b9150506109c2565b5098975050505050505050565b610a5661132f565b610a606000611863565b565b600080610a6e83610856565b9050610562816118b5565b60075460009063ffffffff831610610a92576000610802565b60078263ffffffff1681548110610aab57610aab6126c4565b6000918252602090912001546001600160a01b031692915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614610b3b5760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b60448201526064016105bf565b6040516323b872dd60e01b81526001600160a01b038681166004830152306024830152604482018690527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af1158015610bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd4919061276b565b50610be984610be460005461168e565b611963565b5050505050565b610bf861132f565b610c36838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250611a6b915050565b7f01f5838e3dde8cf4817b958fe95be92bdfeccb34317e1d9f58d1cfe5230de231838383604051610c699392919061278d565b60405180910390a1505050565b6000610c8360005461168e565b905090565b610c9061132f565b600d805460ff60a01b19169055565b610ca761132f565b6000610cca600980546001600160601b031981169091556001600160601b031690565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526001600160601b03831660248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a919061276b565b505050565b6000610d7a82610856565b9050610d8581611c6d565b60405163ffffffff8216906001600160a01b038416907fe61e9f0f049b3bfae1ae903a5e3018c02a008aa0d238ffddf23a4fb4c027853690600090a35050565b600080610dd183610856565b905061056281611e09565b600d546001600160a01b03163314610e065760405162461bcd60e51b81526004016105bf90612694565b6001600160a01b038116610e705760405162461bcd60e51b815260206004820152602b60248201527f4e6577206368616f736e6574206f776e6572206d757374206e6f74206265207a60448201526a65726f206164647265737360a81b60648201526084016105bf565b610e7981611e1d565b50565b610e8461132f565b600d54600160a01b900460ff1615610ed65760405162461bcd60e51b815260206004820152601560248201527414dbdc9d1a5d1a5bdb881c1bdbdb081b1bd8dad959605a1b60448201526064016105bf565b6000610ee182611389565b90506000610eee84610856565b9050610efa81836114ab565b81600003610f1057610f0b84611e77565b6106b8565b6106b88483611eeb565b6000610f2461132f565b6000610f2f84610856565b9050610f4381610f3e86610808565b6114ab565b63ffffffff81166000908152600a6020526040812080546bffffffffffffffffffffffff60601b198116909155600160601b90046001600160601b031660405163a9059cbb60e01b81526001600160a01b0386811660048301526001600160601b03831660248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611020919061276b565b50949350505050565b6004546005546000919061103d81836127de565b9250505090565b600b54600160a01b900460ff166110965760405162461bcd60e51b81526020600482015260166024820152754368616f736e6574206973206e6f742061637469766560501b60448201526064016105bf565b600d546001600160a01b031633146110c05760405162461bcd60e51b81526004016105bf90612694565b600b805460ff60a01b191690556040517fbea11dc6cfde2788be7e8a6ceef5c8d181bb1c628ba6d71675fca0e754367c7490600090a1565b61110061132f565b6001600160a01b0381166111655760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105bf565b610e7981611863565b60075460609060008367ffffffffffffffff81111561118f5761118f612755565b6040519080825280602002602001820160405280156111b8578160200160208202803683370190505b50905060005b848110156110205760008686838181106111da576111da6126c4565b90506020020160208101906111ef919061251e565b90508063ffffffff168411611205576000611234565b60078163ffffffff168154811061121e5761121e6126c4565b6000918252602090912001546001600160a01b03165b838381518110611246576112466126c4565b6001600160a01b03909216602092830291909101909101525080611269816126f0565b9150506111be565b61127961132f565b600d805460ff60a01b1916600160a01b179055565b63ffffffff8082166000908152600a60205260408120549091600160c01b909104168082036112ff5760405162461bcd60e51b815260206004820152601960248201527f4f70657261746f7220616c726561647920656c696769626c650000000000000060448201526064016105bf565b6105627f000000000000000000000000000000000000000000000000000000000000000063ffffffff83166127f1565b600b546001600160a01b03163314610a605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105bf565b60006108027f00000000000000000000000000000000000000000000000000000000000000008361281a565b6001600160a01b0382166000908152600360205260409020541561142e5760405162461bcd60e51b815260206004820152602a60248201527f4f70657261746f7220697320616c7265616479207265676973746572656420696044820152691b881d1a19481c1bdbdb60b21b60648201526084016105bf565b600061143983610856565b63ffffffff169050806000036114555761145283611f5c565b90505b600061145f61201f565b9050600061146e854385612102565b905061147e8282866000546121db565b600055600160ff1b82176001600160a01b0390951660009081526003602052604090209490945550505050565b60085463ffffffff8084166000908152600a60209081526040808320815160808101835290546001600160601b03818116808452600160601b8304821695840195909552600160c01b8204871693830193909352600160e01b9004909416606085018190529416939061151e908561282e565b6115289190612855565b9050816040015163ffffffff1660000361155f57808260200181815161154e9190612880565b6001600160601b03169052506115a2565b6009805482919060009061157d9084906001600160601b0316612880565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b506001600160601b03918216815263ffffffff928316606082019081529383166000908152600a60209081526040918290208351815492850151939094015196518616600160e01b026001600160e01b0397909616600160c01b02969096166001600160c01b03928516600160601b026001600160c01b03199092169390941692909217919091171617179055565b60008061163d836121f7565b9050600061164b8460031c90565b60008181527fdc686ec4a0ff239c70e7c7c36e8f853eced3bc8618f48d2b816da2a74311237e602052604090205490915061084781846020021c63ffffffff1690565b63ffffffff8116602082901c5b80156108505763ffffffff8116919091019060201c61169b565b6000816001036116c757506000919050565b601f5b82816001901b106116de57600019016116ca565b60010192915050565b6000808080855b82611752576000196001871b0181169150803060405160200161172892919091825260601b6001600160601b031916602082015260340190565b6040516020818303038152906040528051906020012090508782101561174d57600192505b6116ee565b9097909650945050505050565b60008282828061176e8361168e565b87106117b35760405162461bcd60e51b8152602060048201526014602482015273125b99195e08195e18d959591cc81dd95a59da1d60621b60448201526064016105bf565b6117bd8385612207565b9450905060025b60078111611814576117d6838361223e565b6000828152600160209081526040808320848452909152902054945092506117fe8486612207565b955091508061180c816126f0565b9150506117c4565b5061181f828261223e565b979650505050505050565b6000600161183a60036002612984565b6118469061010061281a565b611851906002612984565b61185b91906127de565b909116919050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60085463ffffffff8083166000908152600a60209081526040808320815160808101835290546001600160601b038181168352600160601b8204811694830194909452600160c01b81048616928201839052600160e01b9004909416606085015291931691908303611958576060810151815160009163ffffffff169061193c908561282e565b6119469190612855565b90508082602001516108479190612880565b602001519392505050565b60008163ffffffff16116119b15760405162461bcd60e51b8152602060048201526015602482015274139bc81c9958da5c1a595b9d1cc81a5b881c1bdbdb605a1b60448201526064016105bf565b6008546000906119d190600160601b90046001600160601b031684612880565b905060006119e563ffffffff841683612990565b905060006119f963ffffffff8516846129b6565b600880549192508391600090611a199084906001600160601b0316612880565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550806008600c6101000a8154816001600160601b0302191690836001600160601b031602179055505050505050565b604080516080810182526000808252602082018190529181018290526060810182905260085490916001600160601b039091169080611aca7f0000000000000000000000000000000000000000000000000000000000000000866127de565b905060005b8651811015611c64576000878281518110611aec57611aec6126c4565b60209081029190910181015163ffffffff8082166000908152600a845260409081902080546001600160601b03600160601b82048116968d01969096529485168b52600160c01b85048316918b01829052600160e01b90940490911660608a015290925015611b7f578363ffffffff16876040015163ffffffff161015611b7a5763ffffffff841660408801525b611bcb565b63ffffffff808516604089015260608801518851911690611ba0908861282e565b611baa9190612855565b94508487602001818151611bbe9190612880565b6001600160601b03169052505b6001600160601b038681168089526020890151835460408b015160608c01516001600160e01b0319909216600160601b93909516929092027fffffffff00000000ffffffffffffffffffffffff0000000000000000000000001693909317909117600160c01b63ffffffff92831602176001600160e01b0316600160e01b91909216021790555080611c5c816126f0565b915050611acf565b50505050505050565b611c7681611e09565b611cc25760405162461bcd60e51b815260206004820152601960248201527f4f70657261746f72207374696c6c20696e656c696769626c650000000000000060448201526064016105bf565b60085463ffffffff8083166000908152600a60209081526040808320815160808101835290546001600160601b03818116808452600160601b8304821695840195909552600160c01b8204871693830193909352600160e01b90049094166060850181905294169390611d35908561282e565b611d3f9190612855565b600980549192508291600090611d5f9084906001600160601b0316612880565b82546001600160601b039182166101009390930a928302928202191691909117909155938416835250506000604080830182815263ffffffff9586168352600a602090815291909220835181549285015193516060909501518716600160e01b026001600160e01b0395909716600160c01b02949094166001600160c01b03938616600160601b026001600160c01b03199093169490951693909317171691909117919091179055565b600042611e158361128e565b111592915050565b600d80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527ff7d2871c195d5dcbeca7c9bfb4f7ae4149d0915a5d3d03c8c2286c9a24e932be91016107de565b6001600160a01b03811660009081526003602052604081205490819003611eb05760405162461bcd60e51b81526004016105bf906129dc565b60006001600160ff1b0382169050611eca81600054612268565b600055610d6a836001600160a01b0316600090815260036020526040812055565b6001600160a01b038216600090815260036020526040902054611f205760405162461bcd60e51b81526004016105bf906129dc565b6001600160a01b03821660009081526003602052604081205490546001600160ff1b03821690611f5390829085906122dd565b60005550505050565b60075460009063ffffffff811115611faf5760405162461bcd60e51b8152602060048201526016602482015275141bdbdb0818d85c1858da5d1e48195e18d95959195960521b60448201526064016105bf565b6001600160a01b03929092166000818152600660205260408120805463ffffffff191663ffffffff86161790556007805460018101825591527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191690911790555090565b60045460009081600761203460036002612984565b61203e9190612984565b6120498360016127f1565b10905080156120665761205d8260016127f1565b60045550919050565b600554806120a55760405162461bcd60e51b815260206004820152600c60248201526b141bdbdb081a5cc8199d5b1b60a21b60448201526064016105bf565b600060056120b46001846127de565b815481106120c4576120c46126c4565b9060005260206000200154905060058054806120e2576120e2612a22565b600190038181906000526020600020016000905590558094505050505090565b600067ffffffffffffffff83111561211c5761211c612a38565b63ffffffff82111561213057612130612a38565b6001600160601b0319606085901b166000600161214f60036002612984565b61215b9061010061281a565b612166906002612984565b61217091906127de565b84169050600061218260036002612984565b61218e9061010061281a565b600161219c60036002612984565b6121a89061010061281a565b6121b39060606127de565b6121be906002612984565b6121c891906127de565b8716901b92909217179150509392505050565b6000848152600260205260408120849055610847858484612307565b6000600161185160036002612984565b6000818363ffffffff81165b80831061223457600193909301929091039060201c63ffffffff8116612213565b50505b9250929050565b6000600161224e60036002612984565b61225891906127de565b8216600384901b17905092915050565b600080600160045461227a91906127de565b9050838114600061228d868280886121db565b9050811561229f576004839055610847565b600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00186905595945050505050565b6000826122e985611631565b14612300576122f9848484612307565b9050610562565b5080610562565b6000808080858760075b6002811061238857612322826121f7565b955061232e8260031c90565b60008281526001602090815260408083208484528252909120805463ffffffff928a0283811b198216938816901b9290921790819055909650945091506123748461168e565b92508061238081612a4e565b915050612311565b50612392816121f7565b945063ffffffff6020860281811b198916918416901b179998505050505050505050565b80356001600160a01b03811681146123cd57600080fd5b919050565b6000602082840312156123e457600080fd5b610562826123b6565b6000806040838503121561240057600080fd5b612409836123b6565b946020939093013593505050565b60008083601f84011261242957600080fd5b50813567ffffffffffffffff81111561244157600080fd5b6020830191508360208260051b850101111561223757600080fd5b6000806020838503121561246f57600080fd5b823567ffffffffffffffff81111561248657600080fd5b61249285828601612417565b90969095509350505050565b600080604083850312156124b157600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156124fe57835163ffffffff16835292840192918401916001016124dc565b50909695505050505050565b803563ffffffff811681146123cd57600080fd5b60006020828403121561253057600080fd5b6105628261250a565b60008060008060006080868803121561255157600080fd5b61255a866123b6565b94506020860135935061256f604087016123b6565b9250606086013567ffffffffffffffff8082111561258c57600080fd5b818801915088601f8301126125a057600080fd5b8135818111156125af57600080fd5b8960208285010111156125c157600080fd5b9699959850939650602001949392505050565b6000806000604084860312156125e957600080fd5b833567ffffffffffffffff81111561260057600080fd5b61260c86828701612417565b909790965060209590950135949350505050565b6000806040838503121561263357600080fd5b61263c836123b6565b915061264a602084016123b6565b90509250929050565b6020808252825182820181905260009190848201906040850190845b818110156124fe5783516001600160a01b03168352928401929184019160010161266f565b6020808252601690820152752737ba103a34329031b430b7b9b732ba1037bbb732b960511b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612702576127026126da565b5060010190565b60208082528181018390526000908460408401835b8681101561274a576001600160a01b03612737846123b6565b168252918301919083019060010161271e565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561277d57600080fd5b8151801515811461056257600080fd5b6040808252810183905260008460608301825b868110156127cb5763ffffffff6127b68461250a565b168252602092830192909101906001016127a0565b5060209390930193909352509392505050565b81810381811115610802576108026126da565b80820180821115610802576108026126da565b634e487b7160e01b600052601260045260246000fd5b60008261282957612829612804565b500490565b6001600160601b0382811682821603908082111561284e5761284e6126da565b5092915050565b6001600160601b03818116838216028082169190828114612878576128786126da565b505092915050565b6001600160601b0381811683821601908082111561284e5761284e6126da565b600181815b808511156128db5781600019048211156128c1576128c16126da565b808516156128ce57918102915b93841c93908002906128a5565b509250929050565b6000826128f257506001610802565b816128ff57506000610802565b8160018114612915576002811461291f5761293b565b6001915050610802565b60ff841115612930576129306126da565b50506001821b610802565b5060208310610133831016604e8410600b841016171561295e575081810a610802565b61296883836128a0565b806000190482111561297c5761297c6126da565b029392505050565b600061056283836128e3565b60006001600160601b03808416806129aa576129aa612804565b92169190910492915050565b60006001600160601b03808416806129d0576129d0612804565b92169190910692915050565b60208082526026908201527f4f70657261746f72206973206e6f74207265676973746572656420696e20746860408201526519481c1bdbdb60d21b606082015260800190565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052600160045260246000fd5b600081612a5d57612a5d6126da565b50600019019056fea26469706673582212200777efb6bbaffaf3c12f9366651c0738fd0510bf19a96c3af0a337226cca78d364736f6c63430008110033000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee50000000000000000000000000000000000000000000000000de0b6b3a7640000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061021b5760003560e01c806396c82e5711610125578063dc7520c5116100ad578063f2fde38b1161007c578063f2fde38b146104e9578063f7186ce014610329578063f7c618c1146104fc578063f7f9a8fa14610523578063f83d08ba1461054357600080fd5b8063dc7520c5146104b3578063e20981ca146104c6578063e7bfd899146104d9578063f23baf4a146104e157600080fd5b8063a9649414116100f4578063a964941414610453578063b0f3828e14610466578063b2f3db4d1461047a578063c0a3f9eb1461048d578063c545b3a9146104a057600080fd5b806396c82e571461041c578063a4e2d63414610424578063a69df4b514610438578063a7a7d3911461044057600080fd5b80636b1906f8116101a8578063873e31fa11610177578063873e31fa146103a75780638871ca5d146103d25780638da5cb5b146103e55780638f4ffcb1146103f6578063942f68921461040957600080fd5b80636b1906f8146103295780636c2530b914610354578063715018a6146103745780637c2cf6cd1461037c57600080fd5b806343a3db30116101ef57806343a3db30146102a15780634de824f0146102c85780635757ed5b146102db5780635a48b46b146102ee578063660186e61461031657600080fd5b8062983b7314610220578063241a418814610246578063398ece9c1461025b5780633e723fc91461028e575b600080fd5b61023361022e3660046123d2565b61054b565b6040519081526020015b60405180910390f35b6102596102543660046123ed565b610569565b005b61027e6102693660046123d2565b600c6020526000908152604090205460ff1681565b604051901515815260200161023d565b61025961029c36600461245c565b6106be565b6102337f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b61027e6102d63660046123ed565b6107ea565b6102336102e93660046123d2565b610808565b6103016102fc3660046123d2565b610856565b60405163ffffffff909116815260200161023d565b61027e6103243660046123d2565b610877565b61027e6103373660046123d2565b6001600160a01b0316600090815260036020526040902054151590565b61036761036236600461249e565b6108ac565b60405161023d91906124c0565b610259610a4e565b600d5461038f906001600160a01b031681565b6040516001600160a01b03909116815260200161023d565b6103ba6103b53660046123d2565b610a62565b6040516001600160601b03909116815260200161023d565b61038f6103e036600461251e565b610a79565b600b546001600160a01b031661038f565b610259610404366004612539565b610ac6565b6102596104173660046125d4565b610bf0565b610233610c76565b600d5461027e90600160a01b900460ff1681565b610259610c88565b6009546103ba906001600160601b031681565b6102596104613660046123d2565b610c9f565b600b5461027e90600160a01b900460ff1681565b6102596104883660046123d2565b610d6f565b61027e61049b3660046123d2565b610dc5565b6102596104ae3660046123d2565b610ddc565b6102596104c13660046123ed565b610e7c565b6103ba6104d4366004612620565b610f1a565b610233611029565b610259611044565b6102596104f73660046123d2565b6110f8565b61038f7f000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee581565b61053661053136600461245c565b61116e565b60405161023d9190612653565b610259611271565b60008061055783610856565b90506105628161128e565b9392505050565b61057161132f565b600d54600160a01b900460ff16156105c85760405162461bcd60e51b815260206004820152601560248201527414dbdc9d1a5d1a5bdb881c1bdbdb081b1bd8dad959605a1b60448201526064015b60405180910390fd5b60006105d382611389565b90506000811161061d5760405162461bcd60e51b81526020600482015260156024820152744f70657261746f72206e6f7420656c696769626c6560581b60448201526064016105bf565b600b54600160a01b900460ff1615610697576001600160a01b0383166000908152600c602052604090205460ff166106975760405162461bcd60e51b815260206004820152601e60248201527f4e6f742062657461206f70657261746f7220666f72206368616f736e6574000060448201526064016105bf565b6106a183826113b5565b60006106ac84610856565b90506106b881836114ab565b50505050565b600b54600160a01b900460ff166107105760405162461bcd60e51b81526020600482015260166024820152754368616f736e6574206973206e6f742061637469766560501b60448201526064016105bf565b600d546001600160a01b0316331461073a5760405162461bcd60e51b81526004016105bf90612694565b60005b818110156107ac576001600c600085858581811061075d5761075d6126c4565b905060200201602081019061077291906123d2565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806107a4816126f0565b91505061073d565b507f79b60dc9f29a0514f5ce9bf1e89b7add7a22440cde3b203c03a842e3b534071b82826040516107de929190612709565b60405180910390a15050565b60006107f583610808565b6107fe83611389565b1490505b92915050565b6001600160a01b038116600090815260036020526040812054806000036108325750600092915050565b6001600160ff1b038116600061084782611631565b95945050505050565b50919050565b6001600160a01b031660009081526006602052604090205463ffffffff1690565b60008061088383610856565b90506105628163ffffffff9081166000908152600a6020526040902054600160c01b9004161590565b600d54606090600160a01b900460ff166109085760405162461bcd60e51b815260206004820152601760248201527f536f72746974696f6e20706f6f6c20756e6c6f636b656400000000000000000060448201526064016105bf565b600080549083906109188361168e565b90506000811161096a5760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768206f70657261746f727320696e20706f6f6c0000000060448201526064016105bf565b600080610976836116b5565b905060008867ffffffffffffffff81111561099357610993612755565b6040519080825280602002602001820160405280156109bc578160200160208202803683370190505b50905060005b89811015610a41576109d58587856116e7565b9650935060006109e5858961175f565b600081815260026020526040902054909150610a008161182a565b848481518110610a1257610a126126c4565b602002602001019063ffffffff16908163ffffffff168152505050508080610a39906126f0565b9150506109c2565b5098975050505050505050565b610a5661132f565b610a606000611863565b565b600080610a6e83610856565b9050610562816118b5565b60075460009063ffffffff831610610a92576000610802565b60078263ffffffff1681548110610aab57610aab6126c4565b6000918252602090912001546001600160a01b031692915050565b7f000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee56001600160a01b0316836001600160a01b031614610b3b5760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b60448201526064016105bf565b6040516323b872dd60e01b81526001600160a01b038681166004830152306024830152604482018690527f000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee516906323b872dd906064016020604051808303816000875af1158015610bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd4919061276b565b50610be984610be460005461168e565b611963565b5050505050565b610bf861132f565b610c36838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250611a6b915050565b7f01f5838e3dde8cf4817b958fe95be92bdfeccb34317e1d9f58d1cfe5230de231838383604051610c699392919061278d565b60405180910390a1505050565b6000610c8360005461168e565b905090565b610c9061132f565b600d805460ff60a01b19169055565b610ca761132f565b6000610cca600980546001600160601b031981169091556001600160601b031690565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526001600160601b03831660248301529192507f000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee59091169063a9059cbb906044016020604051808303816000875af1158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a919061276b565b505050565b6000610d7a82610856565b9050610d8581611c6d565b60405163ffffffff8216906001600160a01b038416907fe61e9f0f049b3bfae1ae903a5e3018c02a008aa0d238ffddf23a4fb4c027853690600090a35050565b600080610dd183610856565b905061056281611e09565b600d546001600160a01b03163314610e065760405162461bcd60e51b81526004016105bf90612694565b6001600160a01b038116610e705760405162461bcd60e51b815260206004820152602b60248201527f4e6577206368616f736e6574206f776e6572206d757374206e6f74206265207a60448201526a65726f206164647265737360a81b60648201526084016105bf565b610e7981611e1d565b50565b610e8461132f565b600d54600160a01b900460ff1615610ed65760405162461bcd60e51b815260206004820152601560248201527414dbdc9d1a5d1a5bdb881c1bdbdb081b1bd8dad959605a1b60448201526064016105bf565b6000610ee182611389565b90506000610eee84610856565b9050610efa81836114ab565b81600003610f1057610f0b84611e77565b6106b8565b6106b88483611eeb565b6000610f2461132f565b6000610f2f84610856565b9050610f4381610f3e86610808565b6114ab565b63ffffffff81166000908152600a6020526040812080546bffffffffffffffffffffffff60601b198116909155600160601b90046001600160601b031660405163a9059cbb60e01b81526001600160a01b0386811660048301526001600160601b03831660248301529192507f000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee59091169063a9059cbb906044016020604051808303816000875af1158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611020919061276b565b50949350505050565b6004546005546000919061103d81836127de565b9250505090565b600b54600160a01b900460ff166110965760405162461bcd60e51b81526020600482015260166024820152754368616f736e6574206973206e6f742061637469766560501b60448201526064016105bf565b600d546001600160a01b031633146110c05760405162461bcd60e51b81526004016105bf90612694565b600b805460ff60a01b191690556040517fbea11dc6cfde2788be7e8a6ceef5c8d181bb1c628ba6d71675fca0e754367c7490600090a1565b61110061132f565b6001600160a01b0381166111655760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105bf565b610e7981611863565b60075460609060008367ffffffffffffffff81111561118f5761118f612755565b6040519080825280602002602001820160405280156111b8578160200160208202803683370190505b50905060005b848110156110205760008686838181106111da576111da6126c4565b90506020020160208101906111ef919061251e565b90508063ffffffff168411611205576000611234565b60078163ffffffff168154811061121e5761121e6126c4565b6000918252602090912001546001600160a01b03165b838381518110611246576112466126c4565b6001600160a01b03909216602092830291909101909101525080611269816126f0565b9150506111be565b61127961132f565b600d805460ff60a01b1916600160a01b179055565b63ffffffff8082166000908152600a60205260408120549091600160c01b909104168082036112ff5760405162461bcd60e51b815260206004820152601960248201527f4f70657261746f7220616c726561647920656c696769626c650000000000000060448201526064016105bf565b6105627f000000000000000000000000000000000000000000000000000000006335a5ff63ffffffff83166127f1565b600b546001600160a01b03163314610a605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105bf565b60006108027f0000000000000000000000000000000000000000000000000de0b6b3a76400008361281a565b6001600160a01b0382166000908152600360205260409020541561142e5760405162461bcd60e51b815260206004820152602a60248201527f4f70657261746f7220697320616c7265616479207265676973746572656420696044820152691b881d1a19481c1bdbdb60b21b60648201526084016105bf565b600061143983610856565b63ffffffff169050806000036114555761145283611f5c565b90505b600061145f61201f565b9050600061146e854385612102565b905061147e8282866000546121db565b600055600160ff1b82176001600160a01b0390951660009081526003602052604090209490945550505050565b60085463ffffffff8084166000908152600a60209081526040808320815160808101835290546001600160601b03818116808452600160601b8304821695840195909552600160c01b8204871693830193909352600160e01b9004909416606085018190529416939061151e908561282e565b6115289190612855565b9050816040015163ffffffff1660000361155f57808260200181815161154e9190612880565b6001600160601b03169052506115a2565b6009805482919060009061157d9084906001600160601b0316612880565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b506001600160601b03918216815263ffffffff928316606082019081529383166000908152600a60209081526040918290208351815492850151939094015196518616600160e01b026001600160e01b0397909616600160c01b02969096166001600160c01b03928516600160601b026001600160c01b03199092169390941692909217919091171617179055565b60008061163d836121f7565b9050600061164b8460031c90565b60008181527fdc686ec4a0ff239c70e7c7c36e8f853eced3bc8618f48d2b816da2a74311237e602052604090205490915061084781846020021c63ffffffff1690565b63ffffffff8116602082901c5b80156108505763ffffffff8116919091019060201c61169b565b6000816001036116c757506000919050565b601f5b82816001901b106116de57600019016116ca565b60010192915050565b6000808080855b82611752576000196001871b0181169150803060405160200161172892919091825260601b6001600160601b031916602082015260340190565b6040516020818303038152906040528051906020012090508782101561174d57600192505b6116ee565b9097909650945050505050565b60008282828061176e8361168e565b87106117b35760405162461bcd60e51b8152602060048201526014602482015273125b99195e08195e18d959591cc81dd95a59da1d60621b60448201526064016105bf565b6117bd8385612207565b9450905060025b60078111611814576117d6838361223e565b6000828152600160209081526040808320848452909152902054945092506117fe8486612207565b955091508061180c816126f0565b9150506117c4565b5061181f828261223e565b979650505050505050565b6000600161183a60036002612984565b6118469061010061281a565b611851906002612984565b61185b91906127de565b909116919050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60085463ffffffff8083166000908152600a60209081526040808320815160808101835290546001600160601b038181168352600160601b8204811694830194909452600160c01b81048616928201839052600160e01b9004909416606085015291931691908303611958576060810151815160009163ffffffff169061193c908561282e565b6119469190612855565b90508082602001516108479190612880565b602001519392505050565b60008163ffffffff16116119b15760405162461bcd60e51b8152602060048201526015602482015274139bc81c9958da5c1a595b9d1cc81a5b881c1bdbdb605a1b60448201526064016105bf565b6008546000906119d190600160601b90046001600160601b031684612880565b905060006119e563ffffffff841683612990565b905060006119f963ffffffff8516846129b6565b600880549192508391600090611a199084906001600160601b0316612880565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550806008600c6101000a8154816001600160601b0302191690836001600160601b031602179055505050505050565b604080516080810182526000808252602082018190529181018290526060810182905260085490916001600160601b039091169080611aca7f000000000000000000000000000000000000000000000000000000006335a5ff866127de565b905060005b8651811015611c64576000878281518110611aec57611aec6126c4565b60209081029190910181015163ffffffff8082166000908152600a845260409081902080546001600160601b03600160601b82048116968d01969096529485168b52600160c01b85048316918b01829052600160e01b90940490911660608a015290925015611b7f578363ffffffff16876040015163ffffffff161015611b7a5763ffffffff841660408801525b611bcb565b63ffffffff808516604089015260608801518851911690611ba0908861282e565b611baa9190612855565b94508487602001818151611bbe9190612880565b6001600160601b03169052505b6001600160601b038681168089526020890151835460408b015160608c01516001600160e01b0319909216600160601b93909516929092027fffffffff00000000ffffffffffffffffffffffff0000000000000000000000001693909317909117600160c01b63ffffffff92831602176001600160e01b0316600160e01b91909216021790555080611c5c816126f0565b915050611acf565b50505050505050565b611c7681611e09565b611cc25760405162461bcd60e51b815260206004820152601960248201527f4f70657261746f72207374696c6c20696e656c696769626c650000000000000060448201526064016105bf565b60085463ffffffff8083166000908152600a60209081526040808320815160808101835290546001600160601b03818116808452600160601b8304821695840195909552600160c01b8204871693830193909352600160e01b90049094166060850181905294169390611d35908561282e565b611d3f9190612855565b600980549192508291600090611d5f9084906001600160601b0316612880565b82546001600160601b039182166101009390930a928302928202191691909117909155938416835250506000604080830182815263ffffffff9586168352600a602090815291909220835181549285015193516060909501518716600160e01b026001600160e01b0395909716600160c01b02949094166001600160c01b03938616600160601b026001600160c01b03199093169490951693909317171691909117919091179055565b600042611e158361128e565b111592915050565b600d80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527ff7d2871c195d5dcbeca7c9bfb4f7ae4149d0915a5d3d03c8c2286c9a24e932be91016107de565b6001600160a01b03811660009081526003602052604081205490819003611eb05760405162461bcd60e51b81526004016105bf906129dc565b60006001600160ff1b0382169050611eca81600054612268565b600055610d6a836001600160a01b0316600090815260036020526040812055565b6001600160a01b038216600090815260036020526040902054611f205760405162461bcd60e51b81526004016105bf906129dc565b6001600160a01b03821660009081526003602052604081205490546001600160ff1b03821690611f5390829085906122dd565b60005550505050565b60075460009063ffffffff811115611faf5760405162461bcd60e51b8152602060048201526016602482015275141bdbdb0818d85c1858da5d1e48195e18d95959195960521b60448201526064016105bf565b6001600160a01b03929092166000818152600660205260408120805463ffffffff191663ffffffff86161790556007805460018101825591527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191690911790555090565b60045460009081600761203460036002612984565b61203e9190612984565b6120498360016127f1565b10905080156120665761205d8260016127f1565b60045550919050565b600554806120a55760405162461bcd60e51b815260206004820152600c60248201526b141bdbdb081a5cc8199d5b1b60a21b60448201526064016105bf565b600060056120b46001846127de565b815481106120c4576120c46126c4565b9060005260206000200154905060058054806120e2576120e2612a22565b600190038181906000526020600020016000905590558094505050505090565b600067ffffffffffffffff83111561211c5761211c612a38565b63ffffffff82111561213057612130612a38565b6001600160601b0319606085901b166000600161214f60036002612984565b61215b9061010061281a565b612166906002612984565b61217091906127de565b84169050600061218260036002612984565b61218e9061010061281a565b600161219c60036002612984565b6121a89061010061281a565b6121b39060606127de565b6121be906002612984565b6121c891906127de565b8716901b92909217179150509392505050565b6000848152600260205260408120849055610847858484612307565b6000600161185160036002612984565b6000818363ffffffff81165b80831061223457600193909301929091039060201c63ffffffff8116612213565b50505b9250929050565b6000600161224e60036002612984565b61225891906127de565b8216600384901b17905092915050565b600080600160045461227a91906127de565b9050838114600061228d868280886121db565b9050811561229f576004839055610847565b600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00186905595945050505050565b6000826122e985611631565b14612300576122f9848484612307565b9050610562565b5080610562565b6000808080858760075b6002811061238857612322826121f7565b955061232e8260031c90565b60008281526001602090815260408083208484528252909120805463ffffffff928a0283811b198216938816901b9290921790819055909650945091506123748461168e565b92508061238081612a4e565b915050612311565b50612392816121f7565b945063ffffffff6020860281811b198916918416901b179998505050505050505050565b80356001600160a01b03811681146123cd57600080fd5b919050565b6000602082840312156123e457600080fd5b610562826123b6565b6000806040838503121561240057600080fd5b612409836123b6565b946020939093013593505050565b60008083601f84011261242957600080fd5b50813567ffffffffffffffff81111561244157600080fd5b6020830191508360208260051b850101111561223757600080fd5b6000806020838503121561246f57600080fd5b823567ffffffffffffffff81111561248657600080fd5b61249285828601612417565b90969095509350505050565b600080604083850312156124b157600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156124fe57835163ffffffff16835292840192918401916001016124dc565b50909695505050505050565b803563ffffffff811681146123cd57600080fd5b60006020828403121561253057600080fd5b6105628261250a565b60008060008060006080868803121561255157600080fd5b61255a866123b6565b94506020860135935061256f604087016123b6565b9250606086013567ffffffffffffffff8082111561258c57600080fd5b818801915088601f8301126125a057600080fd5b8135818111156125af57600080fd5b8960208285010111156125c157600080fd5b9699959850939650602001949392505050565b6000806000604084860312156125e957600080fd5b833567ffffffffffffffff81111561260057600080fd5b61260c86828701612417565b909790965060209590950135949350505050565b6000806040838503121561263357600080fd5b61263c836123b6565b915061264a602084016123b6565b90509250929050565b6020808252825182820181905260009190848201906040850190845b818110156124fe5783516001600160a01b03168352928401929184019160010161266f565b6020808252601690820152752737ba103a34329031b430b7b9b732ba1037bbb732b960511b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612702576127026126da565b5060010190565b60208082528181018390526000908460408401835b8681101561274a576001600160a01b03612737846123b6565b168252918301919083019060010161271e565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561277d57600080fd5b8151801515811461056257600080fd5b6040808252810183905260008460608301825b868110156127cb5763ffffffff6127b68461250a565b168252602092830192909101906001016127a0565b5060209390930193909352509392505050565b81810381811115610802576108026126da565b80820180821115610802576108026126da565b634e487b7160e01b600052601260045260246000fd5b60008261282957612829612804565b500490565b6001600160601b0382811682821603908082111561284e5761284e6126da565b5092915050565b6001600160601b03818116838216028082169190828114612878576128786126da565b505092915050565b6001600160601b0381811683821601908082111561284e5761284e6126da565b600181815b808511156128db5781600019048211156128c1576128c16126da565b808516156128ce57918102915b93841c93908002906128a5565b509250929050565b6000826128f257506001610802565b816128ff57506000610802565b8160018114612915576002811461291f5761293b565b6001915050610802565b60ff841115612930576129306126da565b50506001821b610802565b5060208310610133831016604e8410600b841016171561295e575081810a610802565b61296883836128a0565b806000190482111561297c5761297c6126da565b029392505050565b600061056283836128e3565b60006001600160601b03808416806129aa576129aa612804565b92169190910492915050565b60006001600160601b03808416806129d0576129d0612804565b92169190910692915050565b60208082526026908201527f4f70657261746f72206973206e6f74207265676973746572656420696e20746860408201526519481c1bdbdb60d21b606082015260800190565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052600160045260246000fd5b600081612a5d57612a5d6126da565b50600019019056fea26469706673582212200777efb6bbaffaf3c12f9366651c0738fd0510bf19a96c3af0a337226cca78d364736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee50000000000000000000000000000000000000000000000000de0b6b3a7640000
-----Decoded View---------------
Arg [0] : _rewardToken (address): 0xCdF7028ceAB81fA0C6971208e83fa7872994beE5
Arg [1] : _poolWeightDivisor (uint256): 1000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000cdf7028ceab81fa0c6971208e83fa7872994bee5
Arg [1] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 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.