Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
10868964 | 1573 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract contains unverified libraries: StackLib
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BondedSortitionPool
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.5.17; import "./AbstractSortitionPool.sol"; import "./RNG.sol"; import "./api/IStaking.sol"; import "./api/IBonding.sol"; import "./DynamicArray.sol"; /// @title Bonded 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 and bonding requirements. /// @dev Keeping pool up to date cannot be done eagerly as proliferation of /// privileged customers could be used to perform DOS attacks by increasing the /// cost of such updates. When a sortition pool prospectively selects an /// operator, the selected operator’s eligibility status and weight needs to be /// checked and, if necessary, updated in the sortition pool. If the changes /// would be detrimental to the operator, the operator selection is performed /// again with the updated input to ensure correctness. /// The pool should specify a reasonable minimum bondable value for operators /// trying to join the pool, to prevent griefing the selection. contract BondedSortitionPool is AbstractSortitionPool { using DynamicArray for DynamicArray.UintArray; using DynamicArray for DynamicArray.AddressArray; using RNG for RNG.State; struct PoolParams { IStaking stakingContract; uint256 minimumStake; IBonding bondingContract; // Defines the minimum unbounded value the operator needs to have to be // eligible to join and stay in the sortition pool. Operators not // satisfying minimum bondable value are removed from the pool. uint256 minimumBondableValue; // Bond required from each operator for the currently pending group // selection. If operator does not have at least this unbounded value, // it is skipped during the selection. uint256 requestedBond; // The weight divisor in the pool can differ from the minimum stake uint256 poolWeightDivisor; address owner; } PoolParams poolParams; constructor( IStaking _stakingContract, IBonding _bondingContract, uint256 _minimumStake, uint256 _minimumBondableValue, uint256 _poolWeightDivisor, address _poolOwner ) public { require(_minimumStake > 0, "Minimum stake cannot be zero"); poolParams = PoolParams( _stakingContract, _minimumStake, _bondingContract, _minimumBondableValue, 0, _poolWeightDivisor, _poolOwner ); } /// @notice Selects a new group of operators of the provided size based on /// the provided pseudo-random seed and bonding requirements. All operators /// in the group are unique. /// /// If there are not enough operators in a pool to form a group or not /// enough operators are eligible for work selection given the bonding /// requirements, the function fails. /// @param groupSize Size of the requested group /// @param seed Pseudo-random number used to select operators to group /// @param minimumStake The current minimum stake value /// @param bondValue Size of the requested bond per operator function selectSetGroup( uint256 groupSize, bytes32 seed, uint256 minimumStake, uint256 bondValue ) public returns (address[] memory) { PoolParams memory params = initializeSelectionParams( minimumStake, bondValue ); require(msg.sender == params.owner, "Only owner may select groups"); uint256 paramsPtr; // solium-disable-next-line security/no-inline-assembly assembly { paramsPtr := params } return generalizedSelectGroup(groupSize, seed, paramsPtr, true); } /// @notice Sets the minimum bondable value required from the operator /// so that it is eligible to be in the pool. The pool should specify /// a reasonable minimum requirement for operators trying to join the pool /// to prevent griefing group selection. /// @param minimumBondableValue The minimum bondable value required from the /// operator. function setMinimumBondableValue(uint256 minimumBondableValue) public { require( msg.sender == poolParams.owner, "Only owner may update minimum bond value" ); poolParams.minimumBondableValue = minimumBondableValue; } /// @notice Returns the minimum bondable value required from the operator /// so that it is eligible to be in the pool. function getMinimumBondableValue() public view returns (uint256) { return poolParams.minimumBondableValue; } function initializeSelectionParams(uint256 minimumStake, uint256 bondValue) internal returns (PoolParams memory params) { params = poolParams; if (params.requestedBond != bondValue) { params.requestedBond = bondValue; } if (params.minimumStake != minimumStake) { params.minimumStake = minimumStake; poolParams.minimumStake = minimumStake; } return params; } // Return the eligible weight of the operator, // which may differ from the weight in the pool. // Return 0 if ineligible. function getEligibleWeight(address operator) internal view returns (uint256) { address ownerAddress = poolParams.owner; // Get the amount of bondable value available for this pool. // We only care that this covers one single bond // regardless of the weight of the operator in the pool. uint256 bondableValue = poolParams.bondingContract.availableUnbondedValue( operator, ownerAddress, address(this) ); // Don't query stake if bond is insufficient. if (bondableValue < poolParams.minimumBondableValue) { return 0; } uint256 eligibleStake = poolParams.stakingContract.eligibleStake( operator, ownerAddress ); // Weight = floor(eligibleStake / poolWeightDivisor) // but only if eligibleStake >= minimumStake. // Ethereum uint256 division performs implicit floor // If eligibleStake < poolWeightDivisor, return 0 = ineligible. if (eligibleStake < poolParams.minimumStake) { return 0; } return (eligibleStake / poolParams.poolWeightDivisor); } function decideFate( uint256 leaf, DynamicArray.AddressArray memory, // `selected`, for future use uint256 paramsPtr ) internal view returns (Fate memory) { PoolParams memory params; // solium-disable-next-line security/no-inline-assembly assembly { params := paramsPtr } address operator = leaf.operator(); uint256 leafWeight = leaf.weight(); if (!isLeafInitialized(leaf)) { return Fate(Decision.Skip, 0); } address ownerAddress = params.owner; // Get the amount of bondable value available for this pool. // We only care that this covers one single bond // regardless of the weight of the operator in the pool. uint256 bondableValue = params.bondingContract.availableUnbondedValue( operator, ownerAddress, address(this) ); // If unbonded value is insufficient for the operator to be in the pool, // delete the operator. if (bondableValue < params.minimumBondableValue) { return Fate(Decision.Delete, 0); } // If unbonded value is sufficient for the operator to be in the pool // but it is not sufficient for the current selection, skip the operator. if (bondableValue < params.requestedBond) { return Fate(Decision.Skip, 0); } uint256 eligibleStake = params.stakingContract.eligibleStake( operator, ownerAddress ); // Weight = floor(eligibleStake / poolWeightDivisor) // Ethereum uint256 division performs implicit floor uint256 eligibleWeight = eligibleStake / params.poolWeightDivisor; if (eligibleWeight < leafWeight || eligibleStake < params.minimumStake) { return Fate(Decision.Delete, 0); } return Fate(Decision.Select, 0); } }
pragma solidity 0.5.17; interface IBonding { // Gives the amount of ETH // the `operator` has made available for bonding by the `bondCreator`. // If the operator doesn't exist, // or the bond creator isn't authorized, // returns 0. function availableUnbondedValue( address operator, address bondCreator, address authorizedSortitionPool ) external view returns (uint256); }
pragma solidity 0.5.17; interface IStaking { // Gives the amount of KEEP tokens staked by the `operator` // eligible for work selection in the specified `operatorContract`. // // If the operator doesn't exist or hasn't finished initializing, // or the operator contract hasn't been authorized for the operator, // returns 0. function eligibleStake( address operator, address operatorContract ) external view returns (uint256); }
pragma solidity 0.5.17; import "./GasStation.sol"; import "./RNG.sol"; import "./SortitionTree.sol"; import "./DynamicArray.sol"; import "./api/IStaking.sol"; /// @title Abstract Sortition Pool /// @notice Abstract contract encapsulating common logic of all sortition pools. /// @dev Inheriting implementations are expected to implement getEligibleWeight /// function. contract AbstractSortitionPool is SortitionTree, GasStation { using Leaf for uint256; using Position for uint256; using DynamicArray for DynamicArray.UintArray; using DynamicArray for DynamicArray.AddressArray; using RNG for RNG.State; enum Decision { Select, // Add to the group, and use new seed Skip, // Retry with same seed, skip this leaf Delete, // Retry with same seed, delete this leaf UpdateRetry, // Retry with same seed, update this leaf UpdateSelect // Select and reseed, but also update this leaf } struct Fate { Decision decision; // The new weight of the leaf if Decision is Update*, otherwise 0 uint256 maybeWeight; } // Require 10 blocks after joining before the operator can be selected for // a group. This reduces the degrees of freedom miners and other // front-runners have in conducting pool-bumping attacks. // // We don't use the stack of empty leaves until we run out of space on the // rightmost leaf (i.e. after 2 million operators have joined the pool). // It means all insertions are at the right end, so one can't reorder // operators already in the pool until the pool has been filled once. // Because the index is calculated by taking the minimum number of required // random bits, and seeing if it falls in the range of the total pool weight, // the only scenarios where insertions on the right matter are if it crosses // a power of two threshold for the total weight and unlocks another random // bit, or if a random number that would otherwise be discarded happens to // fall within that space. uint256 constant INIT_BLOCKS = 10; uint256 constant GAS_DEPOSIT_SIZE = 1; /// @notice The number of blocks that must be mined before the operator who // joined the pool is eligible for work selection. function operatorInitBlocks() public pure returns (uint256) { return INIT_BLOCKS; } // Return whether the operator is eligible for the pool. function isOperatorEligible(address operator) public view returns (bool) { return getEligibleWeight(operator) > 0; } // Return whether the operator is present in the pool. function isOperatorInPool(address operator) public view returns (bool) { return getFlaggedLeafPosition(operator) != 0; } // Return whether the operator's weight in the pool // matches their eligible weight. function isOperatorUpToDate(address operator) public view returns (bool) { return getEligibleWeight(operator) == getPoolWeight(operator); } // Returns whether the operator has passed the initialization blocks period // to be eligible for the work selection. Reverts if the operator is not in // the pool. function isOperatorInitialized(address operator) public view returns (bool) { require(isOperatorInPool(operator), "Operator is not in the pool"); uint256 flaggedPosition = getFlaggedLeafPosition(operator); uint256 leafPosition = flaggedPosition.unsetFlag(); uint256 leaf = leaves[leafPosition]; return isLeafInitialized(leaf); } // 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 = leaves[leafPosition].weight(); return leafWeight; } } // Add an operator to the pool, // reverting if the operator is already present. function joinPool(address operator) public { uint256 eligibleWeight = getEligibleWeight(operator); require(eligibleWeight > 0, "Operator not eligible"); depositGas(operator); insertOperator(operator, eligibleWeight); } // Update the operator's weight if present and eligible, // or remove from the pool if present and ineligible. function updateOperatorStatus(address operator) public { uint256 eligibleWeight = getEligibleWeight(operator); uint256 inPoolWeight = getPoolWeight(operator); require(eligibleWeight != inPoolWeight, "Operator already up to date"); if (eligibleWeight == 0) { removeOperator(operator); releaseGas(operator); } else { updateOperator(operator, eligibleWeight); } } function generalizedSelectGroup( uint256 groupSize, bytes32 seed, // This uint256 is actually a void pointer. // We can't pass a SelectionParams, // because the implementation of the SelectionParams struct // can vary between different concrete sortition pool implementations. // // Whatever SelectionParams struct is used by the concrete contract // should be created in the `selectGroup`/`selectSetGroup` function, // then coerced into a uint256 to be passed into this function. // The paramsPtr is then passed to the `decideFate` implementation // which can coerce it back into the concrete SelectionParams. // This allows `generalizedSelectGroup` // to work with any desired eligibility logic. uint256 paramsPtr, bool noDuplicates ) internal returns (address[] memory) { uint256 _root = root; bool rootChanged = false; DynamicArray.AddressArray memory selected; selected = DynamicArray.addressArray(groupSize); RNG.State memory rng; rng = RNG.initialize(seed, _root.sumWeight(), groupSize); while (selected.array.length < groupSize) { rng.generateNewIndex(); (uint256 leafPosition, uint256 startingIndex) = pickWeightedLeaf( rng.currentMappedIndex, _root ); uint256 leaf = leaves[leafPosition]; address operator = leaf.operator(); uint256 leafWeight = leaf.weight(); Fate memory fate = decideFate(leaf, selected, paramsPtr); if (fate.decision == Decision.Select) { selected.arrayPush(operator); if (noDuplicates) { rng.addSkippedInterval(startingIndex, leafWeight); } rng.reseed(seed, selected.array.length); continue; } if (fate.decision == Decision.Skip) { rng.addSkippedInterval(startingIndex, leafWeight); continue; } if (fate.decision == Decision.Delete) { // Update the RNG rng.updateInterval(startingIndex, leafWeight, 0); // Remove the leaf and update root _root = removeLeaf(leafPosition, _root); rootChanged = true; // Remove the record of the operator's leaf and release gas removeLeafPositionRecord(operator); releaseGas(operator); continue; } if (fate.decision == Decision.UpdateRetry) { _root = setLeaf(leafPosition, leaf.setWeight(fate.maybeWeight), _root); rootChanged = true; rng.updateInterval(startingIndex, leafWeight, fate.maybeWeight); continue; } if (fate.decision == Decision.UpdateSelect) { _root = setLeaf(leafPosition, leaf.setWeight(fate.maybeWeight), _root); rootChanged = true; selected.arrayPush(operator); rng.updateInterval(startingIndex, leafWeight, fate.maybeWeight); if (noDuplicates) { rng.addSkippedInterval(startingIndex, fate.maybeWeight); } rng.reseed(seed, selected.array.length); continue; } } if (rootChanged) { root = _root; } return selected.array; } function isLeafInitialized(uint256 leaf) internal view returns (bool) { uint256 createdAt = leaf.creationBlock(); return block.number > (createdAt + operatorInitBlocks()); } // Return the eligible weight of the operator, // which may differ from the weight in the pool. // Return 0 if ineligible. function getEligibleWeight(address operator) internal view returns (uint256); function decideFate( uint256 leaf, DynamicArray.AddressArray memory selected, uint256 paramsPtr ) internal view returns (Fate memory); function gasDepositSize() internal pure returns (uint256) { return GAS_DEPOSIT_SIZE; } }
pragma solidity 0.5.17; import "./Leaf.sol"; import "./Interval.sol"; import "./DynamicArray.sol"; library RNG { using DynamicArray for DynamicArray.UintArray; //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Derived constants, do not touch uint256 constant SLOT_COUNT = 2**SLOT_BITS; uint256 constant WEIGHT_WIDTH = 256 / SLOT_COUNT; //////////////////////////////////////////////////////////////////////////// struct State { // RNG output uint256 currentMappedIndex; uint256 currentTruncatedIndex; // The random bytes used to derive indices bytes32 currentSeed; // The full range of indices; // generated random numbers are in [0, fullRange). uint256 fullRange; // The truncated range of indices; // how many non-skipped indices are left to consider. // Random indices are generated within this range, // and mapped to the full range by skipping the specified intervals. uint256 truncatedRange; DynamicArray.UintArray skippedIntervals; } function initialize( bytes32 seed, uint256 range, uint256 expectedSkippedCount ) internal view returns (State memory self) { self = State( 0, 0, seed, range, range, DynamicArray.uintArray(expectedSkippedCount) ); reseed(self, seed, 0); return self; } function reseed( State memory self, bytes32 seed, uint256 nonce ) internal view { self.currentSeed = keccak256( abi.encodePacked(seed, nonce, address(this), "reseed") ); } function retryIndex(State memory self) internal view { uint256 truncatedIndex = self.currentTruncatedIndex; if (self.currentTruncatedIndex < self.truncatedRange) { self.currentMappedIndex = Interval.skip( truncatedIndex, self.skippedIntervals ); } else { generateNewIndex(self); } } function updateInterval( State memory self, uint256 startIndex, uint256 oldWeight, uint256 newWeight ) internal pure { int256 weightDiff = int256(newWeight) - int256(oldWeight); uint256 effectiveStartIndex = startIndex + newWeight; self.truncatedRange = uint256(int256(self.truncatedRange) + weightDiff); self.fullRange = uint256(int256(self.fullRange) + weightDiff); Interval.remapIndices( effectiveStartIndex, weightDiff, self.skippedIntervals ); } function addSkippedInterval( State memory self, uint256 startIndex, uint256 weight ) internal pure { self.truncatedRange -= weight; Interval.insert(self.skippedIntervals, Interval.make(startIndex, weight)); } /// @notice Generate a new index based on the current seed, /// without reseeding first. /// This will result in the same truncated index as before /// if it still fits in the current truncated range. function generateNewIndex(State memory self) internal view { uint256 _truncatedRange = self.truncatedRange; require(_truncatedRange > 0, "Not enough operators in pool"); uint256 bits = bitsRequired(_truncatedRange); uint256 truncatedIndex = truncate(bits, uint256(self.currentSeed)); while (truncatedIndex >= _truncatedRange) { self.currentSeed = keccak256( abi.encodePacked(self.currentSeed, address(this), "generate") ); truncatedIndex = truncate(bits, uint256(self.currentSeed)); } self.currentTruncatedIndex = truncatedIndex; self.currentMappedIndex = Interval.skip( truncatedIndex, self.skippedIntervals ); } /// @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) { uint256 bits = 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) { return input & ((1 << bits) - 1); } /// @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) internal view returns (uint256, bytes32) { uint256 bits = bitsRequired(range); 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 Return an index corresponding to a new, unique leaf. /// /// @dev Gets a new index in a truncated range /// with the weights of all previously selected leaves subtracted. /// This index is then mapped to the full range of possible indices, /// skipping the ranges covered by previous leaves. /// /// @param range The full range in which the unique index should be. /// /// @param state The RNG state. /// /// @param previousLeaves List of indices and weights /// corresponding to the _first_ index of each previously selected leaf, /// and the weight of the same leaf. /// An index number `i` is a starting index of leaf `o` /// if querying for index `i` in the sortition pool returns `o`, /// but querying for `i-1` returns a different leaf. /// This list REALLY needs to be sorted from smallest to largest. /// /// @param sumPreviousWeights The sum of the weights of previous leaves. /// Could be calculated from `previousLeafWeights` /// but providing it explicitly makes the function a bit simpler. /// /// @return uniqueIndex An index in [0, range) that does not overlap /// any of the previousLeaves, /// as determined by the range [index, index + weight). function getUniqueIndex( uint256 range, bytes32 state, uint256[] memory previousLeaves, uint256 sumPreviousWeights ) internal view returns (uint256 uniqueIndex, bytes32 newState) { // Get an index in the truncated range. // The truncated range covers only new leaves, // but has to be mapped to the actual range of indices. uint256 truncatedRange = range - sumPreviousWeights; uint256 truncatedIndex; (truncatedIndex, newState) = getIndex(truncatedRange, state); // Map the truncated index to the available unique indices. uniqueIndex = Interval.skip( truncatedIndex, DynamicArray.convert(previousLeaves) ); return (uniqueIndex, newState); } }
pragma solidity 0.5.17; library DynamicArray { // The in-memory dynamic Array is implemented // by recording the amount of allocated memory // separately from the length of the array. // This gives us a perfectly normal in-memory array // with all the behavior we're used to, // but also makes O(1) `push` operations possible // by expanding into the preallocated memory. // // When we run out of preallocated memory when trying to `push`, // we allocate twice as much and copy the array over. // With linear allocation costs this would amortize to O(1) // but with EVM allocations being actually quadratic // the real performance is a very technical O(N). // Nonetheless, this is reasonably performant in practice. // // A dynamic array can be useful // even when you aren't dealing with an unknown number of items. // Because the array tracks the allocated space // separately from the number of stored items, // you can push items into the dynamic array // and iterate over the currently present items // without tracking their number yourself, // or using a special null value for empty elements. // // Because Solidity doesn't really have useful safety features, // only enough superficial inconveniences // to lull yourself into a false sense of security, // dynamic arrays require a bit of care to handle appropriately. // // First of all, // dynamic arrays must not be created or modified manually. // Use `uintArray(length)`, or `convert(existingArray)` // which will perform a safe and efficient conversion for you. // This also applies to storage; // in-memory dynamic arrays are for efficient in-memory operations only, // and it is unnecessary to store dynamic arrays. // Use a regular `uint256[]` instead. // The contents of `array` may be written like `dynamicArray.array[i] = x` // but never reassign the `array` pointer itself // nor mess with `allocatedMemory` in any way whatsoever. // If you fail to follow these precautions, // dragons inhabiting the no-man's-land // between the array as it's seen by Solidity // and the next thing allocated after it // will be unleashed to wreak havoc upon your memory buffers. // // Second, // because the `array` may be reassigned when pushing, // the following pattern is unsafe: // ``` // UintArray dynamicArray; // uint256 len = dynamicArray.array.length; // uint256[] danglingPointer = dynamicArray.array; // danglingPointer[0] = x; // dynamicArray.push(y); // danglingPointer[0] = z; // uint256 surprise = danglingPointer[len]; // ``` // After the above code block, // `dynamicArray.array[0]` may be either `x` or `z`, // and `surprise` may be `y` or out of bounds. // This will not share your address space with a malevolent agent of chaos, // but it will cause entirely avoidable scratchings of the head. // // Dynamic arrays should be safe to use like ordinary arrays // if you always refer to the array field of the dynamic array // when reading or writing values: // ``` // UintArray dynamicArray; // uint256 len = dynamicArray.array.length; // dynamicArray.array[0] = x; // dynamicArray.push(y); // dynamicArray.array[0] = z; // uint256 notSurprise = dynamicArray.array[len]; // ``` // After this code `notSurprise` is reliably `y`, // and `dynamicArray.array[0]` is `z`. struct UintArray { // XXX: Do not modify this value. // In fact, do not even read it. // There is never a legitimate reason to do anything with this value. // She is quiet and wishes to be left alone. // The silent vigil of `allocatedMemory` // is the only thing standing between your contract // and complete chaos in its memory. // Respect her wish or face the monstrosities she is keeping at bay. uint256 allocatedMemory; // Unlike her sharp and vengeful sister, // `array` is safe to use normally // for anything you might do with a normal `uint256[]`. // Reads and loops will check bounds, // and writing in individual indices like `myArray.array[i] = x` // is perfectly fine. // No curse will befall you as long as you obey this rule: // // XXX: Never try to replace her or separate her from her sister // by writing down the accursed words // `myArray.array = anotherArray` or `lonelyArray = myArray.array`. // // If you do, your cattle will be diseased, // your children will be led astray in the woods, // and your memory will be silently overwritten. // Instead, give her a friend with // `mySecondArray = convert(anotherArray)`, // and call her by her family name first. // She will recognize your respect // and ward your memory against corruption. uint256[] array; } struct AddressArray { uint256 allocatedMemory; address[] array; } /// @notice Create an empty dynamic array, /// with preallocated memory for up to `length` elements. /// @dev Knowing or estimating the preallocated length in advance /// helps avoid frequent early allocations when filling the array. /// @param length The number of items to preallocate space for. /// @return A new dynamic array. function uintArray(uint256 length) internal pure returns (UintArray memory) { uint256[] memory array = _allocateUints(length); return UintArray(length, array); } function addressArray(uint256 length) internal pure returns (AddressArray memory) { address[] memory array = _allocateAddresses(length); return AddressArray(length, array); } /// @notice Convert an existing non-dynamic array into a dynamic array. /// @dev The dynamic array is created /// with allocated memory equal to the length of the array. /// @param array The array to convert. /// @return A new dynamic array, /// containing the contents of the argument `array`. function convert(uint256[] memory array) internal pure returns (UintArray memory) { return UintArray(array.length, array); } function convert(address[] memory array) internal pure returns (AddressArray memory) { return AddressArray(array.length, array); } /// @notice Push `item` into the dynamic array. /// @dev This function will be safe /// as long as you haven't scorned either of the sisters. /// If you have, the dragons will be released /// to wreak havoc upon your memory. /// A spell to dispel the curse exists, /// but a sacred vow prohibits it from being shared /// with those who do not know how to discover it on their own. /// @param self The dynamic array to push into; /// after the call it will be mutated in place to contain the item, /// allocating more memory behind the scenes if necessary. /// @param item The item you wish to push into the array. function arrayPush(UintArray memory self, uint256 item) internal pure { uint256 length = self.array.length; uint256 allocLength = self.allocatedMemory; // The dynamic array is full so we need to allocate more first. // We check for >= instead of == // so that we can put the require inside the conditional, // reducing the gas costs of `push` slightly. if (length >= allocLength) { // This should never happen if `allocatedMemory` isn't messed with. require(length == allocLength, "Array length exceeds allocation"); // Allocate twice the original array length, // then copy the contents over. uint256 newMemory = length * 2; uint256[] memory newArray = _allocateUints(newMemory); _copy(newArray, self.array); self.array = newArray; self.allocatedMemory = newMemory; } // We have enough free memory so we can push into the array. _push(self.array, item); } function arrayPush(AddressArray memory self, address item) internal pure { uint256 length = self.array.length; uint256 allocLength = self.allocatedMemory; if (length >= allocLength) { require(length == allocLength, "Array length exceeds allocation"); uint256 newMemory = length * 2; address[] memory newArray = _allocateAddresses(newMemory); _copy(newArray, self.array); self.array = newArray; self.allocatedMemory = newMemory; } _push(self.array, item); } /// @notice Pop the last item from the dynamic array, /// removing it and decrementing the array length in place. /// @dev This makes the dragons happy /// as they have more space to roam. /// Thus they have no desire to escape and ravage your buffers. /// @param self The array to pop from. /// @return item The previously last element in the array. function arrayPop(UintArray memory self) internal pure returns (uint256 item) { uint256[] memory array = self.array; uint256 length = array.length; require(length > 0, "Can't pop from empty array"); return _pop(array); } function arrayPop(AddressArray memory self) internal pure returns (address item) { address[] memory array = self.array; uint256 length = array.length; require(length > 0, "Can't pop from empty array"); return _pop(array); } /// @notice Allocate an empty array, /// reserving enough memory to safely store `length` items. /// @dev The array starts with zero length, /// but the allocated buffer has space for `length` words. /// "What be beyond the bounds of `array`?" you may ask. /// The answer is: dragons. /// But do not worry, /// for `Array.allocatedMemory` protects your EVM from them. function _allocateUints(uint256 length) private pure returns (uint256[] memory array) { // Calculate the size of the allocated block. // Solidity arrays without a specified constant length // (i.e. `uint256[]` instead of `uint256[8]`) // store the length at the first memory position // and the contents of the array after it, // so we add 1 to the length to account for this. uint256 inMemorySize = (length + 1) * 0x20; // solium-disable-next-line security/no-inline-assembly assembly { // Get some free memory array := mload(0x40) // Write a zero in the length field; // we set the length elsewhere // if we store anything in the array immediately. // When we allocate we only know how many words we reserve, // not how many actually get written. mstore(array, 0) // Move the free memory pointer // to the end of the allocated block. mstore(0x40, add(array, inMemorySize)) } return array; } function _allocateAddresses(uint256 length) private pure returns (address[] memory array) { uint256 inMemorySize = (length + 1) * 0x20; // solium-disable-next-line security/no-inline-assembly assembly { array := mload(0x40) mstore(array, 0) mstore(0x40, add(array, inMemorySize)) } return array; } /// @notice Unsafe function to copy the contents of one array /// into an empty initialized array /// with sufficient free memory available. function _copy(uint256[] memory dest, uint256[] memory src) private pure { // solium-disable-next-line security/no-inline-assembly assembly { let length := mload(src) let byteLength := mul(length, 0x20) // Store the resulting length of the array. mstore(dest, length) // Maintain a write pointer // for the current write location in the destination array // by adding the 32 bytes for the array length // to the starting location. let writePtr := add(dest, 0x20) // Stop copying when the write pointer reaches // the length of the source array. // We can track the endpoint either from the write or read pointer. // This uses the write pointer // because that's the way it was done // in the (public domain) code I stole this from. let end := add(writePtr, byteLength) for { // Initialize a read pointer to the start of the source array, // 32 bytes into its memory. let readPtr := add(src, 0x20) } lt(writePtr, end) { // Increase both pointers by 32 bytes each iteration. writePtr := add(writePtr, 0x20) readPtr := add(readPtr, 0x20) } { // Write the source array into the dest memory // 32 bytes at a time. mstore(writePtr, mload(readPtr)) } } } function _copy(address[] memory dest, address[] memory src) private pure { // solium-disable-next-line security/no-inline-assembly assembly { let length := mload(src) let byteLength := mul(length, 0x20) mstore(dest, length) let writePtr := add(dest, 0x20) let end := add(writePtr, byteLength) for { let readPtr := add(src, 0x20) } lt(writePtr, end) { writePtr := add(writePtr, 0x20) readPtr := add(readPtr, 0x20) } { mstore(writePtr, mload(readPtr)) } } } /// @notice Unsafe function to push past the limit of an array. /// Only use with preallocated free memory. function _push(uint256[] memory array, uint256 item) private pure { // solium-disable-next-line security/no-inline-assembly assembly { // Get array length let length := mload(array) let newLength := add(length, 1) // Calculate how many bytes the array takes in memory, // including the length field. // This is equal to 32 * the incremented length. let arraySize := mul(0x20, newLength) // Calculate the first memory position after the array let nextPosition := add(array, arraySize) // Store the item in the available position mstore(nextPosition, item) // Increment array length mstore(array, newLength) } } function _push(address[] memory array, address item) private pure { // solium-disable-next-line security/no-inline-assembly assembly { let length := mload(array) let newLength := add(length, 1) let arraySize := mul(0x20, newLength) let nextPosition := add(array, arraySize) mstore(nextPosition, item) mstore(array, newLength) } } function _pop(uint256[] memory array) private pure returns (uint256 item) { uint256 length = array.length; // solium-disable-next-line security/no-inline-assembly assembly { // Calculate the memory position of the last element let lastPosition := add(array, mul(length, 0x20)) // Retrieve the last item item := mload(lastPosition) // Decrement array length mstore(array, sub(length, 1)) } return item; } function _pop(address[] memory array) private pure returns (address item) { uint256 length = array.length; // solium-disable-next-line security/no-inline-assembly assembly { let lastPosition := add(array, mul(length, 0x20)) item := mload(lastPosition) mstore(array, sub(length, 1)) } return item; } }
pragma solidity 0.5.17; contract GasStation { mapping(address => mapping(uint256 => uint256)) gasDeposits; function depositGas(address addr) internal { setDeposit(addr, 1); } function releaseGas(address addr) internal { setDeposit(addr, 0); } function setDeposit(address addr, uint256 val) internal { for (uint256 i = 0; i < gasDepositSize(); i++) { gasDeposits[addr][i] = val; } } function gasDepositSize() internal pure returns (uint256); }
pragma solidity 0.5.17; import "./StackLib.sol"; import "./Branch.sol"; import "./Position.sol"; import "./Leaf.sol"; contract SortitionTree { using StackLib for uint256[]; using Branch for uint256; using Position for uint256; using Leaf for uint256; //////////////////////////////////////////////////////////////////////////// // 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 SLOT_MAX = (2**SLOT_WIDTH) - 1; uint256 constant POOL_CAPACITY = SLOT_COUNT**LEVELS; //////////////////////////////////////////////////////////////////////////// // implicit tree // root 8 // level2 64 // level3 512 // level4 4k // level5 32k // level6 256k // level7 2M uint256 root; mapping(uint256 => mapping(uint256 => uint256)) branches; mapping(uint256 => uint256) leaves; // the flagged (see setFlag() and unsetFlag() in Position.sol) positions // of all operators present in the pool mapping(address => uint256) flaggedLeafPosition; // the leaf after the rightmost occupied leaf of each stack uint256 rightmostLeaf; // the empty leaves in each stack // between 0 and the rightmost occupied leaf uint256[] emptyLeaves; constructor() public { root = 0; rightmostLeaf = 0; } // checks if operator is already registered in the pool function isOperatorRegistered(address operator) public view returns (bool) { return getFlaggedLeafPosition(operator) != 0; } // Sum the number of operators in each trunk 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.getSize(); return (nPossiblyUsedLeaves - nEmptyLeaves); } function totalWeight() public view returns (uint256) { return root.sumWeight(); } function insertOperator(address operator, uint256 weight) internal { require( !isOperatorRegistered(operator), "Operator is already registered in the pool" ); uint256 position = getEmptyLeafPosition(); // Record the block the operator was inserted in uint256 theLeaf = Leaf.make(operator, block.number, weight); root = setLeaf(position, theLeaf, root); // Without position flags, // the position 0x000000 would be treated as empty flaggedLeafPosition[operator] = position.setFlag(); } function removeOperator(address operator) internal { uint256 flaggedPosition = getFlaggedLeafPosition(operator); require(flaggedPosition != 0, "Operator is not registered in the pool"); uint256 unflaggedPosition = flaggedPosition.unsetFlag(); root = removeLeaf(unflaggedPosition, root); removeLeafPositionRecord(operator); } 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(); updateLeaf(unflaggedPosition, weight); } function removeLeafPositionRecord(address operator) internal { flaggedLeafPosition[operator] = 0; } function getFlaggedLeafPosition(address operator) internal view returns (uint256) { return flaggedLeafPosition[operator]; } function removeLeaf(uint256 position, uint256 _root) internal returns (uint256) { uint256 rightmostSubOne = rightmostLeaf - 1; bool isRightmost = position == rightmostSubOne; uint256 newRoot = setLeaf(position, 0, _root); if (isRightmost) { rightmostLeaf = rightmostSubOne; } else { emptyLeaves.stackPush(position); } return newRoot; } function updateLeaf(uint256 position, uint256 weight) internal { uint256 oldLeaf = leaves[position]; if (oldLeaf.weight() != weight) { uint256 newLeaf = oldLeaf.setWeight(weight); root = setLeaf(position, newLeaf, root); } } function setLeaf( uint256 position, uint256 theLeaf, uint256 _root ) internal returns (uint256) { uint256 childSlot; uint256 treeNode; uint256 newNode; uint256 nodeWeight = theLeaf.weight(); // set leaf leaves[position] = theLeaf; uint256 parent = position; // set levels 7 to 2 for (uint256 level = 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); } function pickWeightedLeaf(uint256 index, uint256 _root) internal view returns (uint256 leafPosition, uint256 leafFirstIndex) { 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 <= LEVELS; level++) { currentPosition = currentPosition.child(currentSlot); currentNode = branches[level][currentPosition]; (currentSlot, currentIndex) = currentNode.pickWeightedSlot(currentIndex); } // get leaf position leafPosition = currentPosition.child(currentSlot); // get the first index of the leaf // This works because the last weight returned from `pickWeightedSlot()` // equals the "overflow" from getting the current slot. leafFirstIndex = index - currentIndex; } function getEmptyLeafPosition() internal returns (uint256) { uint256 rLeaf = rightmostLeaf; bool spaceOnRight = (rLeaf + 1) < POOL_CAPACITY; if (spaceOnRight) { rightmostLeaf = rLeaf + 1; return rLeaf; } else { bool emptyLeavesInStack = leavesInStack(); require(emptyLeavesInStack, "Pool is full"); return emptyLeaves.stackPop(); } } function leavesInStack() internal view returns (bool) { return emptyLeaves.getSize() > 0; } }
pragma solidity 0.5.17; library StackLib { function stackPeek(uint256[] storage _array) internal view returns (uint256) { require(_array.length > 0, "No value to peek, array is empty"); return (_array[_array.length - 1]); } function stackPush(uint256[] storage _array, uint256 _element) public { _array.push(_element); } function stackPop(uint256[] storage _array) internal returns (uint256) { require(_array.length > 0, "No value to pop, array is empty"); uint256 value = _array[_array.length - 1]; _array.length -= 1; return value; } function getSize(uint256[] storage _array) internal view returns (uint256) { return _array.length; } }
pragma solidity 0.5.17; /// @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 { //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// /// @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) { return position * 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) { uint256 shiftBits = position * 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) & SLOT_MAX; } /// @notice Return `node` with the `position`th slot set to zero. function clearSlot(uint256 node, uint256 position) internal pure returns (uint256) { uint256 shiftBits = position * 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 & ~(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) { uint256 shiftBits = position * SLOT_WIDTH; // Clear the `position`th slot like in `clearSlot()`. uint256 clearedNode = node & ~(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 & 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) { sum = node & 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 >> SLOT_WIDTH; while (newNode > 0) { sum += (newNode & SLOT_MAX); newNode = newNode >> 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) { newIndex = index; uint256 newNode = node; uint256 currentSlotWeight = newNode & SLOT_MAX; while (newIndex >= currentSlotWeight) { newIndex -= currentSlotWeight; slot++; newNode = newNode >> SLOT_WIDTH; currentSlotWeight = newNode & SLOT_MAX; } return (slot, newIndex); } }
pragma solidity 0.5.17; library Position { //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Derived constants, do not touch uint256 constant SLOT_POINTER_MAX = (2**SLOT_BITS) - 1; uint256 constant LEAF_FLAG = 1 << 255; //////////////////////////////////////////////////////////////////////////// // 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 & SLOT_POINTER_MAX; } // Return the parent of a position number function parent(uint256 a) internal pure returns (uint256) { return a >> 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 << SLOT_BITS) | (s & 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 | 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 & (~LEAF_FLAG); } }
pragma solidity 0.5.17; library Leaf { //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Derived constants, do not touch uint256 constant SLOT_COUNT = 2**SLOT_BITS; uint256 constant SLOT_WIDTH = 256 / SLOT_COUNT; uint256 constant SLOT_MAX = (2**SLOT_WIDTH) - 1; uint256 constant WEIGHT_WIDTH = SLOT_WIDTH; uint256 constant WEIGHT_MAX = SLOT_MAX; uint256 constant BLOCKHEIGHT_WIDTH = 96 - WEIGHT_WIDTH; uint256 constant BLOCKHEIGHT_MAX = (2**BLOCKHEIGHT_WIDTH) - 1; //////////////////////////////////////////////////////////////////////////// function make( address _operator, uint256 _creationBlock, uint256 _weight ) internal pure returns (uint256) { // Converting a bytesX type into a larger type // adds zero bytes on the right. uint256 op = uint256(bytes32(bytes20(_operator))); // Bitwise AND the weight to erase // all but the 32 least significant bits uint256 wt = _weight & WEIGHT_MAX; // Erase all but the 64 least significant bits, // then shift left by 32 bits to make room for the weight uint256 cb = (_creationBlock & BLOCKHEIGHT_MAX) << WEIGHT_WIDTH; // Bitwise OR them all together to get // [address operator || uint64 creationBlock || uint32 weight] return (op | cb | wt); } 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 >> WEIGHT_WIDTH) & BLOCKHEIGHT_MAX); } function weight(uint256 leaf) internal pure returns (uint256) { // Weight is stored in the 32 least significant bits. // Bitwise AND ensures that we only get the contents of those bits. return (leaf & WEIGHT_MAX); } function setWeight(uint256 leaf, uint256 newWeight) internal pure returns (uint256) { return ((leaf & ~WEIGHT_MAX) | (newWeight & WEIGHT_MAX)); } }
pragma solidity 0.5.17; import "./Leaf.sol"; import "./DynamicArray.sol"; library Interval { using DynamicArray for DynamicArray.UintArray; //////////////////////////////////////////////////////////////////////////// // 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; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Derived constants, do not touch uint256 constant SLOT_COUNT = 2**SLOT_BITS; uint256 constant SLOT_WIDTH = 256 / SLOT_COUNT; uint256 constant SLOT_MAX = (2**SLOT_WIDTH) - 1; uint256 constant WEIGHT_WIDTH = SLOT_WIDTH; uint256 constant WEIGHT_MAX = SLOT_MAX; uint256 constant START_INDEX_WIDTH = WEIGHT_WIDTH; uint256 constant START_INDEX_MAX = WEIGHT_MAX; uint256 constant START_INDEX_SHIFT = WEIGHT_WIDTH; //////////////////////////////////////////////////////////////////////////// // Interval stores information about a selected interval // inside a single uint256 in a manner similar to Leaf // but optimized for use within group selection // // The information stored consists of: // - weight // - starting index function make(uint256 startingIndex, uint256 weight) internal pure returns (uint256) { uint256 idx = (startingIndex & START_INDEX_MAX) << START_INDEX_SHIFT; uint256 wt = weight & WEIGHT_MAX; return (idx | wt); } function opWeight(uint256 op) internal pure returns (uint256) { return (op & WEIGHT_MAX); } // Return the starting index of the interval function index(uint256 a) internal pure returns (uint256) { return ((a >> WEIGHT_WIDTH) & START_INDEX_MAX); } function setIndex(uint256 op, uint256 i) internal pure returns (uint256) { uint256 shiftedIndex = ((i & START_INDEX_MAX) << WEIGHT_WIDTH); return (op & (~(START_INDEX_MAX << WEIGHT_WIDTH))) | shiftedIndex; } function insert(DynamicArray.UintArray memory intervals, uint256 interval) internal pure { uint256 tempInterval = interval; for (uint256 i = 0; i < intervals.array.length; i++) { uint256 thisInterval = intervals.array[i]; // We can compare the raw underlying uint256 values // because the starting index is stored // in the most significant nonzero bits. if (tempInterval < thisInterval) { intervals.array[i] = tempInterval; tempInterval = thisInterval; } } intervals.arrayPush(tempInterval); } function skip(uint256 truncatedIndex, DynamicArray.UintArray memory intervals) internal pure returns (uint256 mappedIndex) { mappedIndex = truncatedIndex; for (uint256 i = 0; i < intervals.array.length; i++) { uint256 interval = intervals.array[i]; // If the index is greater than the starting index of the `i`th leaf, // we need to skip that leaf. if (mappedIndex >= index(interval)) { // Add the weight of this previous leaf to the index, // ensuring that we skip the leaf. mappedIndex += Leaf.weight(interval); } else { break; } } return mappedIndex; } /// @notice Recalculate the starting indices of the previousLeaves /// when an interval is removed or added at the specified index. /// @dev Applies weightDiff to each starting index in previousLeaves /// that exceeds affectedStartingIndex. /// @param affectedStartingIndex The starting index of the interval. /// @param weightDiff The difference in weight; /// negative for a deleted interval, /// positive for an added interval. /// @param previousLeaves The starting indices and weights /// of the previously selected leaves. /// @return The starting indices of the previous leaves /// in a tree with the affected interval updated. function remapIndices( uint256 affectedStartingIndex, int256 weightDiff, DynamicArray.UintArray memory previousLeaves ) internal pure { uint256 nPreviousLeaves = previousLeaves.array.length; for (uint256 i = 0; i < nPreviousLeaves; i++) { uint256 interval = previousLeaves.array[i]; uint256 startingIndex = index(interval); // If index is greater than the index of the affected interval, // update the starting index by the weight change. if (startingIndex > affectedStartingIndex) { uint256 newIndex = uint256(int256(startingIndex) + weightDiff); previousLeaves.array[i] = setIndex(interval, newIndex); } } } }
{ "libraries": { "@keep-network/sortition-pools/contracts/BondedSortitionPool.sol": { "StackLib": "0xdf6542260a9F768f07030E4895083F804241F4C4" } }, "metadata": { "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IStaking","name":"_stakingContract","type":"address"},{"internalType":"contract IBonding","name":"_bondingContract","type":"address"},{"internalType":"uint256","name":"_minimumStake","type":"uint256"},{"internalType":"uint256","name":"_minimumBondableValue","type":"uint256"},{"internalType":"uint256","name":"_poolWeightDivisor","type":"uint256"},{"internalType":"address","name":"_poolOwner","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"getMinimumBondableValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getPoolWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorEligible","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorInPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorUpToDate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"joinPool","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"operatorInitBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"operatorsInPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"groupSize","type":"uint256"},{"internalType":"bytes32","name":"seed","type":"bytes32"},{"internalType":"uint256","name":"minimumStake","type":"uint256"},{"internalType":"uint256","name":"bondValue","type":"uint256"}],"name":"selectSetGroup","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumBondableValue","type":"uint256"}],"name":"setMinimumBondableValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"updateOperatorStatus","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50604051611b9d380380611b9d833981810160405260c081101561003357600080fd5b508051602082015160408301516060840151608085015160a09095015160008080556004559394929391929091836100b2576040805162461bcd60e51b815260206004820152601c60248201527f4d696e696d756d207374616b652063616e6e6f74206265207a65726f00000000604482015290519081900360640190fd5b6040805160e0810182526001600160a01b03978816808252602082018790529688169181018290526060810185905260006080820181905260a082018590529290971660c0909701879052600780546001600160a01b03199081169097179055600894909455600980548616909417909355600a91909155600b91909155600c55600d80549091169091179055611a4f8061014e6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806396c82e571161008c578063ce6fe19811610066578063ce6fe198146102a7578063e686440f146102af578063e7bfd899146102d5578063f7186ce01461019a576100ea565b806396c82e57146101fa578063a2cca6a214610202578063b476685614610281576100ea565b806347a15f5a116100c857806347a15f5a1461015a5780635757ed5b146101745780636b1906f81461019a578063811918c4146101d4576100ea565b80631ae0e73d146100ef5780631c5b07621461011757806334ce30f01461013d575b600080fd5b6101156004803603602081101561010557600080fd5b50356001600160a01b03166102dd565b005b6101156004803603602081101561012d57600080fd5b50356001600160a01b031661034e565b6101156004803603602081101561015357600080fd5b50356103e8565b610162610436565b60408051918252519081900360200190f35b6101626004803603602081101561018a57600080fd5b50356001600160a01b031661043d565b6101c0600480360360208110156101b057600080fd5b50356001600160a01b0316610491565b604080519115158252519081900360200190f35b6101c0600480360360208110156101ea57600080fd5b50356001600160a01b03166104a4565b61016261053c565b6102316004803603608081101561021857600080fd5b508035906020810135906040810135906060013561054e565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561026d578181015183820152602001610255565b505050509050019250505060405180910390f35b6101c06004803603602081101561029757600080fd5b50356001600160a01b03166105e7565b6101626105fa565b6101c0600480360360208110156102c557600080fd5b50356001600160a01b03166105ff565b61016261061a565b60006102e882610634565b905060008111610337576040805162461bcd60e51b81526020600482015260156024820152744f70657261746f72206e6f7420656c696769626c6560581b604482015290519081900360640190fd5b6103408261078f565b61034a828261079d565b5050565b600061035982610634565b905060006103668361043d565b9050808214156103bd576040805162461bcd60e51b815260206004820152601b60248201527f4f70657261746f7220616c726561647920757020746f20646174650000000000604482015290519081900360640190fd5b816103d9576103cb83610838565b6103d4836108a6565b6103e3565b6103e383836108b1565b505050565b600d546001600160a01b031633146104315760405162461bcd60e51b81526004018080602001828103825260288152602001806119a36028913960400191505060405180910390fd5b600a55565b600a545b90565b6000806104498361091f565b90508061045a57600091505061048c565b60006104658261093a565b6000818152600260205260408120549192509061048190610946565b935061048c92505050565b919050565b600061049c8261091f565b151592915050565b60006104af82610491565b610500576040805162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420696e2074686520706f6f6c0000000000604482015290519081900360640190fd5b600061050b8361091f565b905060006105188261093a565b6000818152600260205260409020549091506105338161094f565b95945050505050565b600061054960005461096e565b905090565b606061055861189e565b610562848461099b565b90508060c001516001600160a01b0316336001600160a01b0316146105ce576040805162461bcd60e51b815260206004820152601c60248201527f4f6e6c79206f776e6572206d61792073656c6563742067726f75707300000000604482015290519081900360640190fd5b806105dc8787836001610a24565b979650505050505050565b6000806105f383610634565b1192915050565b600a90565b600061060a8261043d565b61061383610634565b1492915050565b6004546000908161062b6005610c87565b90910391505090565b600d54600954604080516342bcb96560e01b81526001600160a01b0385811660048301529384166024820181905230604483015291516000949293859316916342bcb965916064808301926020929190829003018186803b15801561069857600080fd5b505afa1580156106ac573d6000803e3d6000fd5b505050506040513d60208110156106c257600080fd5b5051600a549091508110156106dc5760009250505061048c565b6007546040805163afff33ef60e01b81526001600160a01b03878116600483015285811660248301529151600093929092169163afff33ef91604480820192602092909190829003018186803b15801561073557600080fd5b505afa158015610749573d6000803e3d6000fd5b505050506040513d602081101561075f57600080fd5b505160085490915081101561077a576000935050505061048c565b600c54818161078557fe5b0495945050505050565b61079a816001610c8b565b50565b6107a682610491565b156107e25760405162461bcd60e51b815260040180806020018281038252602a8152602001806119f1602a913960400191505060405180910390fd5b60006107ec610ccb565b905060006107fb844385610d50565b905061080a8282600054610d88565b60005561081682610e57565b6001600160a01b03909416600090815260036020526040902093909355505050565b60006108438261091f565b9050806108815760405162461bcd60e51b81526004018080602001828103825260268152602001806119cb6026913960400191505060405180910390fd5b600061088c8261093a565b905061089a81600054610e60565b6000556103e383610f05565b61079a816000610c8b565b6108ba82610491565b6108f55760405162461bcd60e51b81526004018080602001828103825260268152602001806119cb6026913960400191505060405180910390fd5b60006109008361091f565b9050600061090d8261093a565b90506109198184610f1f565b50505050565b6001600160a01b031660009081526003602052604090205490565b6001600160ff1b031690565b63ffffffff1690565b60008061095b83610f67565b90506109656105fa565b01431192915050565b63ffffffff8116602082901c5b80156109955763ffffffff8116919091019060201c61097b565b50919050565b6109a361189e565b506040805160e0810182526007546001600160a01b0390811682526008546020830152600954811692820192909252600a546060820152600b5460808201819052600c5460a0830152600d5490921660c0820152908214610a0657608081018290525b82816020015114610a1e576020810183905260088390555b92915050565b60008054606091610a336118f6565b610a3c88610f84565b9050610a46611910565b610a5988610a538661096e565b8b610fb0565b90505b888260200151511015610c6b57610a7281610ffc565b600080610a838360000151876110f7565b600082815260026020526040812054929450909250610aa1826111db565b90506000610aae83610946565b9050610ab861194e565b610ac384898f6111e1565b9050600081516004811115610ad457fe5b1415610b2657610aea888463ffffffff61141216565b8b15610b0157610b0187868463ffffffff6114aa16565b610b1b8e896020015151896114cd9092919063ffffffff16565b505050505050610a5c565b600181516004811115610b3557fe5b1415610b4c57610b1b87868463ffffffff6114aa16565b600281516004811115610b5b57fe5b1415610b9657610b74878684600063ffffffff61151716565b610b7e868b610e60565b995060019850610b8d83610f05565b610b1b836108a6565b600381516004811115610ba557fe5b1415610bed57610bcc86610bc683602001518761154e90919063ffffffff16565b8c610d88565b995060019850610b1b858383602001518a611517909392919063ffffffff16565b600481516004811115610bfc57fe5b1415610b1b57610c1d86610bc683602001518761154e90919063ffffffff16565b995060019850610c33888463ffffffff61141216565b6020810151610c4d9088908790859063ffffffff61151716565b8b15610b01576020810151610b01908890879063ffffffff6114aa16565b8215610c775760008490555b5060200151979650505050505050565b5490565b60005b610c96611562565b8110156103e3576001600160a01b03831660009081526006602090815260408083208484529091529020829055600101610c8e565b6004546000906220000060018201108015610cef575060018101600455905061043a565b6000610cf9611567565b905080610d3c576040805162461bcd60e51b815260206004820152600c60248201526b141bdbdb081a5cc8199d5b1b60a21b604482015290519081900360640190fd5b610d46600561157a565b935050505061043a565b6bffffffffffffffff00000000602083901b16606084901b6bffffffffffffffffffffffff19161763ffffffff8216175b9392505050565b6000806000806000610d9987610946565b600089815260026020526040902088905590508760075b60028110610e2d57610dc18261160b565b9550610dcc82611611565b600082815260016020908152604080832084845290915290205495509150610dfb85878563ffffffff61161716565b600082815260016020908152604080832086845290915290208190559350610e228461096e565b925060001901610db0565b50610e378161160b565b9450610e4a87868463ffffffff61161716565b9998505050505050505050565b600160ff1b1790565b6004546000906000190183811482610e79868287610d88565b90508115610e8b576004839055610533565b6040805163d2c5b12360e01b81526005600482015260248101889052905173df6542260a9f768f07030e4895083f804241f4c49163d2c5b123916044808301926000929190829003018186803b158015610ee457600080fd5b505af4158015610ef8573d6000803e3d6000fd5b5050505095945050505050565b6001600160a01b0316600090815260036020526040812055565b60008281526002602052604090205481610f3882610946565b146103e3576000610f4f828463ffffffff61154e16565b9050610f5e8482600054610d88565b60005550505050565b600067ffffffffffffffff60086101005b0483901c169050919050565b610f8c6118f6565b6060610f9783611633565b6040805180820190915293845260208401525090919050565b610fb8611910565b6040518060c001604052806000815260200160008152602001858152602001848152602001848152602001610fec84610f84565b90529050610d81818560006114cd565b608081015180611053576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768206f70657261746f727320696e20706f6f6c00000000604482015290519081900360640190fd5b600061105e8261164b565b9050600061107382856040015160001c61166d565b90505b8281106110d8576040808501805182516020808201929092523060601b818501526767656e657261746560c01b60548201528351603c818303018152605c9091019093528251920191909120908190526110d190839061166d565b9050611076565b6020840181905260a08401516110ef90829061167a565b909352505050565b600080838382806111078361096e565b8810611151576040805162461bcd60e51b8152602060048201526014602482015273125b99195e08195e18d959591cc81dd95a59da1d60621b604482015290519081900360640190fd5b611161838563ffffffff6116d716565b9450905060025b600781116111ba57611180838363ffffffff61170d16565b6000828152600160209081526040808320848452909152902054945092506111ae848663ffffffff6116d716565b95509150600101611168565b506111cb828263ffffffff61170d16565b9893909703965091945050505050565b60601c90565b6111e961194e565b6111f161189e565b508160006111fe866111db565b9050600061120b87610946565b90506112168761094f565b61123a5750506040805180820190915260018152600060208201529150610d819050565b60c083015160408085015181516342bcb96560e01b81526001600160a01b03868116600483015280851660248301523060448301529251600093909216916342bcb96591606480820192602092909190829003018186803b15801561129e57600080fd5b505afa1580156112b2573d6000803e3d6000fd5b505050506040513d60208110156112c857600080fd5b505160608601519091508110156112fd57604080518082019091528060025b8152602001600081525095505050505050610d81565b846080015181101561131b57604080518082019091528060016112e7565b84516040805163afff33ef60e01b81526001600160a01b03878116600483015285811660248301529151600093929092169163afff33ef91604480820192602092909190829003018186803b15801561137357600080fd5b505afa158015611387573d6000803e3d6000fd5b505050506040513d602081101561139d57600080fd5b505160a087015190915060009082816113b257fe5b049050848110806113c65750866020015182105b156113ef5750506040805180820190915260028152600060208201529550610d81945050505050565b505060408051808201909152600080825260208201529998505050505050505050565b602082015151825180821061149c57808214611475576040805162461bcd60e51b815260206004820152601f60248201527f4172726179206c656e677468206578636565647320616c6c6f636174696f6e00604482015290519081900360640190fd5b60028202606061148482611633565b905061149481876020015161171a565b602086015284525b610919846020015184611750565b608083018051829003905260a08301516103e3906114c88484611763565b611780565b604080516020808201949094528082019290925230606090811b90830152651c995cd9595960d21b60748301528051605a818403018152607a909201815281519190920120910152565b6080840180518383039081019091526060850180518201905260a08501518483019061154690829084906117f0565b505050505050565b63ffffffff1663ffffffff19919091161790565b600190565b6000806115746005610c87565b11905090565b80546000906115d0576040805162461bcd60e51b815260206004820152601f60248201527f4e6f2076616c756520746f20706f702c20617272617920697320656d70747900604482015290519081900360640190fd5b8154600090839060001981019081106115e557fe5b6000918252602090912001548354909150600019016116048482611965565b5092915050565b60071690565b60031c90565b63ffffffff90811660209290920291821b911b19919091161790565b60408051600081526001929092016020028201905290565b6000601f5b82816001901b106116645760001901611650565b60010192915050565b600190911b600019011690565b8160005b8260200151518110156116045760008360200151828151811061169d57fe5b602002602001015190506116b08161186e565b83106116c8576116bf81610946565b830192506116ce565b50611604565b5060010161167e565b6000818363ffffffff81165b80831061170457600193909301929091039060201c63ffffffff81166116e3565b50509250929050565b60071660039190911b1790565b80516020810281845260208401818101602085015b8183101561174757805183526020928301920161172f565b50505050505050565b8151600101602081028301919091529052565b63ffffffff1667ffffffff0000000060209290921b919091161790565b8060005b8360200151518110156117df576000846020015182815181106117a357fe5b60200260200101519050808310156117d65782856020015183815181106117c657fe5b6020026020010181815250508092505b50600101611784565b506103e3838263ffffffff61141216565b60208101515160005b818110156118675760008360200151828151811061181357fe5b6020026020010151905060006118288261186e565b90508681111561185d5780860161183f838261187f565b8660200151858151811061184f57fe5b602002602001018181525050505b50506001016117f9565b5050505050565b600063ffffffff6008610100610f78565b60201b67ffffffff000000001667ffffffff0000000019919091161790565b6040518060e0016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b604051806040016040528060008152602001606081525090565b6040518060c0016040528060008152602001600081526020016000801916815260200160008152602001600081526020016119496118f6565b905290565b604080518082019091526000808252602082015290565b8154818355818111156103e3576000838152602090206103e391810190830161043a91905b8082111561199e576000815560010161198a565b509056fe4f6e6c79206f776e6572206d617920757064617465206d696e696d756d20626f6e642076616c75654f70657261746f72206973206e6f74207265676973746572656420696e2074686520706f6f6c4f70657261746f7220697320616c7265616479207265676973746572656420696e2074686520706f6f6ca265627a7a72315820a097e08c247284eeeb2f839db380a28c08c9f606e2628ccf5a226fb83658388564736f6c634300051100320000000000000000000000001293a54e160d1cd7075487898d65266081a1545800000000000000000000000027321f84704a599ab740281e285cc4463d89a3d500000000000000000000000000000000000000000000130ee8e7179044400000000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000a7d9e842efb252389d613da88eda3731512e40bd
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806396c82e571161008c578063ce6fe19811610066578063ce6fe198146102a7578063e686440f146102af578063e7bfd899146102d5578063f7186ce01461019a576100ea565b806396c82e57146101fa578063a2cca6a214610202578063b476685614610281576100ea565b806347a15f5a116100c857806347a15f5a1461015a5780635757ed5b146101745780636b1906f81461019a578063811918c4146101d4576100ea565b80631ae0e73d146100ef5780631c5b07621461011757806334ce30f01461013d575b600080fd5b6101156004803603602081101561010557600080fd5b50356001600160a01b03166102dd565b005b6101156004803603602081101561012d57600080fd5b50356001600160a01b031661034e565b6101156004803603602081101561015357600080fd5b50356103e8565b610162610436565b60408051918252519081900360200190f35b6101626004803603602081101561018a57600080fd5b50356001600160a01b031661043d565b6101c0600480360360208110156101b057600080fd5b50356001600160a01b0316610491565b604080519115158252519081900360200190f35b6101c0600480360360208110156101ea57600080fd5b50356001600160a01b03166104a4565b61016261053c565b6102316004803603608081101561021857600080fd5b508035906020810135906040810135906060013561054e565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561026d578181015183820152602001610255565b505050509050019250505060405180910390f35b6101c06004803603602081101561029757600080fd5b50356001600160a01b03166105e7565b6101626105fa565b6101c0600480360360208110156102c557600080fd5b50356001600160a01b03166105ff565b61016261061a565b60006102e882610634565b905060008111610337576040805162461bcd60e51b81526020600482015260156024820152744f70657261746f72206e6f7420656c696769626c6560581b604482015290519081900360640190fd5b6103408261078f565b61034a828261079d565b5050565b600061035982610634565b905060006103668361043d565b9050808214156103bd576040805162461bcd60e51b815260206004820152601b60248201527f4f70657261746f7220616c726561647920757020746f20646174650000000000604482015290519081900360640190fd5b816103d9576103cb83610838565b6103d4836108a6565b6103e3565b6103e383836108b1565b505050565b600d546001600160a01b031633146104315760405162461bcd60e51b81526004018080602001828103825260288152602001806119a36028913960400191505060405180910390fd5b600a55565b600a545b90565b6000806104498361091f565b90508061045a57600091505061048c565b60006104658261093a565b6000818152600260205260408120549192509061048190610946565b935061048c92505050565b919050565b600061049c8261091f565b151592915050565b60006104af82610491565b610500576040805162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420696e2074686520706f6f6c0000000000604482015290519081900360640190fd5b600061050b8361091f565b905060006105188261093a565b6000818152600260205260409020549091506105338161094f565b95945050505050565b600061054960005461096e565b905090565b606061055861189e565b610562848461099b565b90508060c001516001600160a01b0316336001600160a01b0316146105ce576040805162461bcd60e51b815260206004820152601c60248201527f4f6e6c79206f776e6572206d61792073656c6563742067726f75707300000000604482015290519081900360640190fd5b806105dc8787836001610a24565b979650505050505050565b6000806105f383610634565b1192915050565b600a90565b600061060a8261043d565b61061383610634565b1492915050565b6004546000908161062b6005610c87565b90910391505090565b600d54600954604080516342bcb96560e01b81526001600160a01b0385811660048301529384166024820181905230604483015291516000949293859316916342bcb965916064808301926020929190829003018186803b15801561069857600080fd5b505afa1580156106ac573d6000803e3d6000fd5b505050506040513d60208110156106c257600080fd5b5051600a549091508110156106dc5760009250505061048c565b6007546040805163afff33ef60e01b81526001600160a01b03878116600483015285811660248301529151600093929092169163afff33ef91604480820192602092909190829003018186803b15801561073557600080fd5b505afa158015610749573d6000803e3d6000fd5b505050506040513d602081101561075f57600080fd5b505160085490915081101561077a576000935050505061048c565b600c54818161078557fe5b0495945050505050565b61079a816001610c8b565b50565b6107a682610491565b156107e25760405162461bcd60e51b815260040180806020018281038252602a8152602001806119f1602a913960400191505060405180910390fd5b60006107ec610ccb565b905060006107fb844385610d50565b905061080a8282600054610d88565b60005561081682610e57565b6001600160a01b03909416600090815260036020526040902093909355505050565b60006108438261091f565b9050806108815760405162461bcd60e51b81526004018080602001828103825260268152602001806119cb6026913960400191505060405180910390fd5b600061088c8261093a565b905061089a81600054610e60565b6000556103e383610f05565b61079a816000610c8b565b6108ba82610491565b6108f55760405162461bcd60e51b81526004018080602001828103825260268152602001806119cb6026913960400191505060405180910390fd5b60006109008361091f565b9050600061090d8261093a565b90506109198184610f1f565b50505050565b6001600160a01b031660009081526003602052604090205490565b6001600160ff1b031690565b63ffffffff1690565b60008061095b83610f67565b90506109656105fa565b01431192915050565b63ffffffff8116602082901c5b80156109955763ffffffff8116919091019060201c61097b565b50919050565b6109a361189e565b506040805160e0810182526007546001600160a01b0390811682526008546020830152600954811692820192909252600a546060820152600b5460808201819052600c5460a0830152600d5490921660c0820152908214610a0657608081018290525b82816020015114610a1e576020810183905260088390555b92915050565b60008054606091610a336118f6565b610a3c88610f84565b9050610a46611910565b610a5988610a538661096e565b8b610fb0565b90505b888260200151511015610c6b57610a7281610ffc565b600080610a838360000151876110f7565b600082815260026020526040812054929450909250610aa1826111db565b90506000610aae83610946565b9050610ab861194e565b610ac384898f6111e1565b9050600081516004811115610ad457fe5b1415610b2657610aea888463ffffffff61141216565b8b15610b0157610b0187868463ffffffff6114aa16565b610b1b8e896020015151896114cd9092919063ffffffff16565b505050505050610a5c565b600181516004811115610b3557fe5b1415610b4c57610b1b87868463ffffffff6114aa16565b600281516004811115610b5b57fe5b1415610b9657610b74878684600063ffffffff61151716565b610b7e868b610e60565b995060019850610b8d83610f05565b610b1b836108a6565b600381516004811115610ba557fe5b1415610bed57610bcc86610bc683602001518761154e90919063ffffffff16565b8c610d88565b995060019850610b1b858383602001518a611517909392919063ffffffff16565b600481516004811115610bfc57fe5b1415610b1b57610c1d86610bc683602001518761154e90919063ffffffff16565b995060019850610c33888463ffffffff61141216565b6020810151610c4d9088908790859063ffffffff61151716565b8b15610b01576020810151610b01908890879063ffffffff6114aa16565b8215610c775760008490555b5060200151979650505050505050565b5490565b60005b610c96611562565b8110156103e3576001600160a01b03831660009081526006602090815260408083208484529091529020829055600101610c8e565b6004546000906220000060018201108015610cef575060018101600455905061043a565b6000610cf9611567565b905080610d3c576040805162461bcd60e51b815260206004820152600c60248201526b141bdbdb081a5cc8199d5b1b60a21b604482015290519081900360640190fd5b610d46600561157a565b935050505061043a565b6bffffffffffffffff00000000602083901b16606084901b6bffffffffffffffffffffffff19161763ffffffff8216175b9392505050565b6000806000806000610d9987610946565b600089815260026020526040902088905590508760075b60028110610e2d57610dc18261160b565b9550610dcc82611611565b600082815260016020908152604080832084845290915290205495509150610dfb85878563ffffffff61161716565b600082815260016020908152604080832086845290915290208190559350610e228461096e565b925060001901610db0565b50610e378161160b565b9450610e4a87868463ffffffff61161716565b9998505050505050505050565b600160ff1b1790565b6004546000906000190183811482610e79868287610d88565b90508115610e8b576004839055610533565b6040805163d2c5b12360e01b81526005600482015260248101889052905173df6542260a9f768f07030e4895083f804241f4c49163d2c5b123916044808301926000929190829003018186803b158015610ee457600080fd5b505af4158015610ef8573d6000803e3d6000fd5b5050505095945050505050565b6001600160a01b0316600090815260036020526040812055565b60008281526002602052604090205481610f3882610946565b146103e3576000610f4f828463ffffffff61154e16565b9050610f5e8482600054610d88565b60005550505050565b600067ffffffffffffffff60086101005b0483901c169050919050565b610f8c6118f6565b6060610f9783611633565b6040805180820190915293845260208401525090919050565b610fb8611910565b6040518060c001604052806000815260200160008152602001858152602001848152602001848152602001610fec84610f84565b90529050610d81818560006114cd565b608081015180611053576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768206f70657261746f727320696e20706f6f6c00000000604482015290519081900360640190fd5b600061105e8261164b565b9050600061107382856040015160001c61166d565b90505b8281106110d8576040808501805182516020808201929092523060601b818501526767656e657261746560c01b60548201528351603c818303018152605c9091019093528251920191909120908190526110d190839061166d565b9050611076565b6020840181905260a08401516110ef90829061167a565b909352505050565b600080838382806111078361096e565b8810611151576040805162461bcd60e51b8152602060048201526014602482015273125b99195e08195e18d959591cc81dd95a59da1d60621b604482015290519081900360640190fd5b611161838563ffffffff6116d716565b9450905060025b600781116111ba57611180838363ffffffff61170d16565b6000828152600160209081526040808320848452909152902054945092506111ae848663ffffffff6116d716565b95509150600101611168565b506111cb828263ffffffff61170d16565b9893909703965091945050505050565b60601c90565b6111e961194e565b6111f161189e565b508160006111fe866111db565b9050600061120b87610946565b90506112168761094f565b61123a5750506040805180820190915260018152600060208201529150610d819050565b60c083015160408085015181516342bcb96560e01b81526001600160a01b03868116600483015280851660248301523060448301529251600093909216916342bcb96591606480820192602092909190829003018186803b15801561129e57600080fd5b505afa1580156112b2573d6000803e3d6000fd5b505050506040513d60208110156112c857600080fd5b505160608601519091508110156112fd57604080518082019091528060025b8152602001600081525095505050505050610d81565b846080015181101561131b57604080518082019091528060016112e7565b84516040805163afff33ef60e01b81526001600160a01b03878116600483015285811660248301529151600093929092169163afff33ef91604480820192602092909190829003018186803b15801561137357600080fd5b505afa158015611387573d6000803e3d6000fd5b505050506040513d602081101561139d57600080fd5b505160a087015190915060009082816113b257fe5b049050848110806113c65750866020015182105b156113ef5750506040805180820190915260028152600060208201529550610d81945050505050565b505060408051808201909152600080825260208201529998505050505050505050565b602082015151825180821061149c57808214611475576040805162461bcd60e51b815260206004820152601f60248201527f4172726179206c656e677468206578636565647320616c6c6f636174696f6e00604482015290519081900360640190fd5b60028202606061148482611633565b905061149481876020015161171a565b602086015284525b610919846020015184611750565b608083018051829003905260a08301516103e3906114c88484611763565b611780565b604080516020808201949094528082019290925230606090811b90830152651c995cd9595960d21b60748301528051605a818403018152607a909201815281519190920120910152565b6080840180518383039081019091526060850180518201905260a08501518483019061154690829084906117f0565b505050505050565b63ffffffff1663ffffffff19919091161790565b600190565b6000806115746005610c87565b11905090565b80546000906115d0576040805162461bcd60e51b815260206004820152601f60248201527f4e6f2076616c756520746f20706f702c20617272617920697320656d70747900604482015290519081900360640190fd5b8154600090839060001981019081106115e557fe5b6000918252602090912001548354909150600019016116048482611965565b5092915050565b60071690565b60031c90565b63ffffffff90811660209290920291821b911b19919091161790565b60408051600081526001929092016020028201905290565b6000601f5b82816001901b106116645760001901611650565b60010192915050565b600190911b600019011690565b8160005b8260200151518110156116045760008360200151828151811061169d57fe5b602002602001015190506116b08161186e565b83106116c8576116bf81610946565b830192506116ce565b50611604565b5060010161167e565b6000818363ffffffff81165b80831061170457600193909301929091039060201c63ffffffff81166116e3565b50509250929050565b60071660039190911b1790565b80516020810281845260208401818101602085015b8183101561174757805183526020928301920161172f565b50505050505050565b8151600101602081028301919091529052565b63ffffffff1667ffffffff0000000060209290921b919091161790565b8060005b8360200151518110156117df576000846020015182815181106117a357fe5b60200260200101519050808310156117d65782856020015183815181106117c657fe5b6020026020010181815250508092505b50600101611784565b506103e3838263ffffffff61141216565b60208101515160005b818110156118675760008360200151828151811061181357fe5b6020026020010151905060006118288261186e565b90508681111561185d5780860161183f838261187f565b8660200151858151811061184f57fe5b602002602001018181525050505b50506001016117f9565b5050505050565b600063ffffffff6008610100610f78565b60201b67ffffffff000000001667ffffffff0000000019919091161790565b6040518060e0016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b604051806040016040528060008152602001606081525090565b6040518060c0016040528060008152602001600081526020016000801916815260200160008152602001600081526020016119496118f6565b905290565b604080518082019091526000808252602082015290565b8154818355818111156103e3576000838152602090206103e391810190830161043a91905b8082111561199e576000815560010161198a565b509056fe4f6e6c79206f776e6572206d617920757064617465206d696e696d756d20626f6e642076616c75654f70657261746f72206973206e6f74207265676973746572656420696e2074686520706f6f6c4f70657261746f7220697320616c7265616479207265676973746572656420696e2074686520706f6f6ca265627a7a72315820a097e08c247284eeeb2f839db380a28c08c9f606e2628ccf5a226fb83658388564736f6c63430005110032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001293a54e160d1cd7075487898d65266081a1545800000000000000000000000027321f84704a599ab740281e285cc4463d89a3d500000000000000000000000000000000000000000000130ee8e7179044400000000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000a7d9e842efb252389d613da88eda3731512e40bd
-----Decoded View---------------
Arg [0] : _stakingContract (address): 0x1293a54e160D1cd7075487898d65266081A15458
Arg [1] : _bondingContract (address): 0x27321f84704a599aB740281E285cc4463d89A3D5
Arg [2] : _minimumStake (uint256): 90000000000000000000000
Arg [3] : _minimumBondableValue (uint256): 20000000000000000000
Arg [4] : _poolWeightDivisor (uint256): 1000000000000000000
Arg [5] : _poolOwner (address): 0xA7d9E842EFB252389d613dA88EDa3731512e40bD
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000001293a54e160d1cd7075487898d65266081a15458
Arg [1] : 00000000000000000000000027321f84704a599ab740281e285cc4463d89a3d5
Arg [2] : 00000000000000000000000000000000000000000000130ee8e7179044400000
Arg [3] : 000000000000000000000000000000000000000000000001158e460913d00000
Arg [4] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [5] : 000000000000000000000000a7d9e842efb252389d613da88eda3731512e40bd
Deployed Bytecode Sourcemap
1096:6729:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1096:6729:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3959:237:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3959:237:0;-1:-1:-1;;;;;3959:237:0;;:::i;:::-;;4315:406;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4315:406:0;-1:-1:-1;;;;;4315:406:0;;:::i;3989:243:1:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3989:243:1;;:::i;4360:114::-;;;:::i;:::-;;;;;;;;;;;;;;;;3522:348:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3522:348:0;-1:-1:-1;;;;;3522:348:0;;:::i;1767:130:9:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1767:130:9;-1:-1:-1;;;;;1767:130:9;;:::i;:::-;;;;;;;;;;;;;;;;;;3072:352:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3072:352:0;-1:-1:-1;;;;;3072:352:0;;:::i;2486:87:9:-;;;:::i;3095:530:1:-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;3095:530:1;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;3095:530:1;;;;;;;;;;;;;;;;;2349:122:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2349:122:0;-1:-1:-1;;;;;2349:122:0;;:::i;2197:89::-;;;:::i;2752:145::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2752:145:0;-1:-1:-1;;;;;2752:145:0;;:::i;1948:534:9:-;;;:::i;3959:237:0:-;4008:22;4033:27;4051:8;4033:17;:27::i;:::-;4008:52;;4091:1;4074:14;:18;4066:52;;;;;-1:-1:-1;;;4066:52:0;;;;;;;;;;;;-1:-1:-1;;;4066:52:0;;;;;;;;;;;;;;;4125:20;4136:8;4125:10;:20::i;:::-;4151:40;4166:8;4176:14;4151;:40::i;:::-;3959:237;;:::o;4315:406::-;4376:22;4401:27;4419:8;4401:17;:27::i;:::-;4376:52;;4434:20;4457:23;4471:8;4457:13;:23::i;:::-;4434:46;;4513:12;4495:14;:30;;4487:70;;;;;-1:-1:-1;;;4487:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;4568:19;4564:153;;4597:24;4612:8;4597:14;:24::i;:::-;4629:20;4640:8;4629:10;:20::i;:::-;4564:153;;;4670:40;4685:8;4695:14;4670;:40::i;:::-;4315:406;;;:::o;3989:243:1:-;4094:16;;-1:-1:-1;;;;;4094:16:1;4080:10;:30;4065:101;;;;-1:-1:-1;;;4065:101:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4173:31;:54;3989:243::o;4360:114::-;4438:31;;4360:114;;:::o;3522:348:0:-;3584:7;3599:23;3625:32;3648:8;3625:22;:32::i;:::-;3599:58;-1:-1:-1;3667:20:0;3663:203;;3704:1;3697:8;;;;;3663:203;3726:20;3749:27;:15;:25;:27::i;:::-;3784:18;3805:20;;;:6;:20;;;;;;3726:50;;-1:-1:-1;3784:18:0;3805:29;;:27;:29::i;:::-;3784:50;-1:-1:-1;3842:17:0;;-1:-1:-1;;;3842:17:0;3522:348;;;;:::o;1767:130:9:-;1836:4;1855:32;1878:8;1855:22;:32::i;:::-;:37;;;1767:130;-1:-1:-1;;1767:130:9:o;3072:352:0:-;3142:4;3162:26;3179:8;3162:16;:26::i;:::-;3154:66;;;;;-1:-1:-1;;;3154:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;3227:23;3253:32;3276:8;3253:22;:32::i;:::-;3227:58;;3291:20;3314:27;:15;:25;:27::i;:::-;3347:12;3362:20;;;:6;:20;;;;;;3291:50;;-1:-1:-1;3396:23:0;3362:20;3396:17;:23::i;:::-;3389:30;3072:352;-1:-1:-1;;;;;3072:352:0:o;2486:87:9:-;2530:7;2552:16;:4;;:14;:16::i;:::-;2545:23;;2486:87;:::o;3095:530:1:-;3229:16;3253:24;;:::i;:::-;3280:68;3313:12;3333:9;3280:25;:68::i;:::-;3253:95;;3376:6;:12;;;-1:-1:-1;;;;;3362:26:1;:10;-1:-1:-1;;;;;3362:26:1;;3354:67;;;;;-1:-1:-1;;;3354:67:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;3540:6;3564:56;3587:9;3598:4;3540:6;3615:4;3564:22;:56::i;:::-;3557:63;3095:530;-1:-1:-1;;;;;;;3095:530:1:o;2349:122:0:-;2416:4;2465:1;2435:27;2453:8;2435:17;:27::i;:::-;:31;;2349:122;-1:-1:-1;;2349:122:0:o;2197:89::-;2017:2;2197:89;:::o;2752:145::-;2819:4;2869:23;2883:8;2869:13;:23::i;:::-;2838:27;2856:8;2838:17;:27::i;:::-;:54;;2752:145;-1:-1:-1;;2752:145:0:o;1948:534:9:-;2278:13;;1996:7;;;2406:21;:11;:19;:21::i;:::-;2442:34;;;;-1:-1:-1;;1948:534:9;:::o;5025:1058:1:-;5131:16;;5356:26;;:112;;;-1:-1:-1;;;5356:112:1;;-1:-1:-1;;;;;5356:112:1;;;;;;;5131:16;;;5356:112;;;;;;5457:4;5356:112;;;;;;5093:7;;5131:16;;5093:7;;5356:26;;:49;;:112;;;;;;;;;;;;;;:26;:112;;;5:2:-1;;;;30:1;27;20:12;5:2;5356:112:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5356:112:1;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5356:112:1;5545:31;;5356:112;;-1:-1:-1;5529:47:1;;5525:76;;;5593:1;5586:8;;;;;;5525:76;5631:10;:26;:82;;;-1:-1:-1;;;5631:82:1;;-1:-1:-1;;;;;5631:82:1;;;;;;;;;;;;;;;;5607:21;;5631:26;;;;;:40;;:82;;;;;;;;;;;;;;;:26;:82;;;5:2:-1;;;;30:1;27;20:12;5:2;5631:82:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5631:82:1;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5631:82:1;5972:23;;5631:82;;-1:-1:-1;5956:39:1;;5952:68;;;6012:1;6005:8;;;;;;;5952:68;6049:28;;6033:13;6049:28;6033:44;;;;;;5025:1058;-1:-1:-1;;;;;5025:1058:1:o;113:73:4:-;162:19;173:4;179:1;162:10;:19::i;:::-;113:73;:::o;2577:537:9:-;2666:30;2687:8;2666:20;:30::i;:::-;2665:31;2650:104;;;;-1:-1:-1;;;2650:104:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2761:16;2780:22;:20;:22::i;:::-;2761:41;;2861:15;2879:41;2889:8;2899:12;2913:6;2879:9;:41::i;:::-;2861:59;;2934:32;2942:8;2952:7;2961:4;;2934:7;:32::i;:::-;2927:4;:39;3091:18;:8;:16;:18::i;:::-;-1:-1:-1;;;;;3059:29:9;;;;;;;:19;:29;;;;;:50;;;;-1:-1:-1;;;2577:537:9:o;3118:346::-;3175:23;3201:32;3224:8;3201:22;:32::i;:::-;3175:58;-1:-1:-1;3247:20:9;3239:71;;;;-1:-1:-1;;;3239:71:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3316:25;3344:27;:15;:25;:27::i;:::-;3316:55;;3384:35;3395:17;3414:4;;3384:10;:35::i;:::-;3377:4;:42;3425:34;3450:8;3425:24;:34::i;190:73:4:-;239:19;250:4;256:1;239:10;:19::i;3468:346:9:-;3556:30;3577:8;3556:20;:30::i;:::-;3541:99;;;;-1:-1:-1;;;3541:99:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3647:23;3673:32;3696:8;3673:22;:32::i;:::-;3647:58;;3711:25;3739:27;:15;:25;:27::i;:::-;3711:55;;3772:37;3783:17;3802:6;3772:10;:37::i;:::-;3468:346;;;;:::o;3927:143::-;-1:-1:-1;;;;;4036:29:9;4012:7;4036:29;;;:19;:29;;;;;;;3927:143::o;1818:96:7:-;-1:-1:-1;;;;;1893:16:7;;1818:96::o;2059:229:6:-;626:19;2265:17;;2059:229::o;7816:184:0:-;7880:4;7892:17;7912:20;:4;:18;:20::i;:::-;7892:40;;7974:20;:18;:20::i;:::-;7962:32;7946:12;:49;;7816:184;-1:-1:-1;;7816:184:0:o;3918:418:2:-;870:19;3999:15;;775:16;4191:18;;;4215:101;4222:11;;4215:101;;870:19;4251:18;;4243:27;;;;;775:16;4288:21;4215:101;;;-1:-1:-1;3918:418:2;;;:::o;4478:414:1:-;4580:24;;:::i;:::-;-1:-1:-1;4614:19:1;;;;;;;;4623:10;4614:19;-1:-1:-1;;;;;4614:19:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4644:33;;4640:86;;4687:20;;;:32;;;4640:86;4759:12;4736:6;:19;;;:35;4732:136;;4781:19;;;:34;;;4823:23;:38;;;4732:136;4478:414;;;;:::o;4725:3087:0:-;5570:13;5586:4;;5546:16;;5627:41;;:::i;:::-;5685:36;5711:9;5685:25;:36::i;:::-;5674:47;;5728:20;;:::i;:::-;5760:50;5775:4;5781:17;:5;:15;:17::i;:::-;5800:9;5760:14;:50::i;:::-;5754:56;;5817:1915;5848:9;5824:8;:14;;;:21;:33;5817:1915;;;5867:22;:3;:20;:22::i;:::-;5899:20;5921:21;5946:71;5972:3;:22;;;6004:5;5946:16;:71::i;:::-;6026:12;6041:20;;;:6;:20;;;;;;5898:119;;-1:-1:-1;5898:119:0;;-1:-1:-1;6088:15:0;6041:20;6088:13;:15::i;:::-;6069:34;;6111:18;6132:13;:4;:11;:13::i;:::-;6111:34;;6154:16;;:::i;:::-;6173:37;6184:4;6190:8;6200:9;6173:10;:37::i;:::-;6154:56;-1:-1:-1;6240:15:0;6223:13;;:32;;;;;;;;;6219:251;;;6267:28;:8;6286;6267:28;:18;:28;:::i;:::-;6309:12;6305:90;;;6335:49;:3;6358:13;6373:10;6335:49;:22;:49;:::i;:::-;6404:39;6415:4;6421:8;:14;;;:21;6404:3;:10;;:39;;;;;:::i;:::-;6453:8;;;;;;;;6219:251;6498:13;6481;;:30;;;;;;;;;6477:122;;;6523:49;:3;6546:13;6561:10;6523:49;:22;:49;:::i;6477:122::-;6627:15;6610:13;;:32;;;;;;;;;6606:411;;;6680:48;:3;6699:13;6714:10;6726:1;6680:48;:18;:48;:::i;:::-;6789:31;6800:12;6814:5;6789:10;:31::i;:::-;6781:39;;6844:4;6830:18;;6926:34;6951:8;6926:24;:34::i;:::-;6970:20;6981:8;6970:10;:20::i;6606:411::-;7045:20;7028:13;;:37;;;;;;;;;7024:251;;;7085:62;7093:12;7107:32;7122:4;:16;;;7107:4;:14;;:32;;;;:::i;:::-;7141:5;7085:7;:62::i;:::-;7077:70;;7171:4;7157:18;;7185:63;7204:13;7219:10;7231:4;:16;;;7185:3;:18;;:63;;;;;;:::i;7024:251::-;7303:21;7286:13;;:38;;;;;;;;;7282:444;;;7344:62;7352:12;7366:32;7381:4;:16;;;7366:4;:14;;:32;;;;:::i;7344:62::-;7336:70;-1:-1:-1;7430:4:0;;-1:-1:-1;7444:28:0;:8;7463;7444:28;:18;:28;:::i;:::-;7528:16;;;;7482:63;;:3;;7501:13;;7516:10;;7482:63;:18;:63;:::i;:::-;7559:12;7555:96;;;7623:16;;;;7585:55;;:3;;7608:13;;7585:55;:22;:55;:::i;5817:1915::-;7741:11;7737:44;;;7762:4;:12;;;7737:44;-1:-1:-1;7793:14:0;;;;4725:3087;-1:-1:-1;;;;;;;4725:3087:0:o;582:106:10:-;670:13;;582:106::o;267:154:4:-;334:9;329:88;353:16;:14;:16::i;:::-;349:1;:20;329:88;;;-1:-1:-1;;;;;384:17:4;;;;;;:11;:17;;;;;;;;:20;;;;;;;;:26;;;371:3;;329:88;;6502:385:9;6583:13;;6552:7;;935:18;6631:1;6623:9;;6622:27;6655:228;;;;-1:-1:-1;6705:1:9;6697:9;;6681:13;:25;6697:5;-1:-1:-1;6714:12:9;;6655:228;6747:23;6773:15;:13;:15::i;:::-;6747:41;;6804:18;6796:43;;;;;-1:-1:-1;;;6796:43:9;;;;;;;;;;;;-1:-1:-1;;;6796:43:9;;;;;;;;;;;;;;;6854:22;:11;:20;:22::i;:::-;6847:29;;;;;;;943:713:6;1464:50;578:16;1464:50;;;;1188:18;;;;-1:-1:-1;;1180:27:6;1638:7;626:19;1311:20;;1638:12;943:713;;;;;;:::o;4721:740:9:-;4822:7;4837:17;4860:16;4882:15;4903:18;4924:16;:7;:14;:16::i;:::-;4963;;;;:6;:16;;;;;:26;;;4903:37;-1:-1:-1;4970:8:9;554:1;5052:302;5090:1;5081:5;:10;5052:302;;5122:13;:6;:11;:13::i;:::-;5110:25;;5152:15;:6;:13;:15::i;:::-;5186;;;;:8;:15;;;;;;;;:23;;;;;;;;;;-1:-1:-1;5143:24:9;-1:-1:-1;5227:39:9;5186:23;5244:9;5255:10;5227:39;:16;:39;:::i;:::-;5274:15;;;;:8;:15;;;;;;;;:23;;;;;;;;:33;;;5217:49;-1:-1:-1;5328:19:9;5217:49;5328:17;:19::i;:::-;5315:32;-1:-1:-1;;;5093:7:9;5052:302;;;;5394:13;:6;:11;:13::i;:::-;5382:25;-1:-1:-1;5420:36:9;:5;5382:25;5445:10;5420:36;:13;:36;:::i;:::-;5413:43;4721:740;-1:-1:-1;;;;;;;;;4721:740:9:o;1432:91:7:-;-1:-1:-1;;;1505:13:7;;1432:91::o;4074:389:9:-;4196:13;;4153:7;;-1:-1:-1;;4196:17:9;4238:27;;;4153:7;4290:27;4238:8;4153:7;4311:5;4290:7;:27::i;:::-;4272:45;;4328:11;4324:115;;;4349:13;:31;;;4324:115;;;4401:31;;;-1:-1:-1;;;4401:31:9;;:11;:31;;;;;;;;;;;;:21;;;;:31;;;;;-1:-1:-1;;4401:31:9;;;;;;;:21;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;4401:31:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4401:31:9;;;;4451:7;4074:389;-1:-1:-1;;;;;4074:389:9:o;3818:105::-;-1:-1:-1;;;;;3885:29:9;3917:1;3885:29;;;:19;:29;;;;;:33;3818:105::o;4467:250::-;4536:15;4554:16;;;:6;:16;;;;;;4600:6;4580:16;4554;4580:14;:16::i;:::-;:26;4576:137;;4616:15;4634:25;:7;4652:6;4634:25;:17;:25;:::i;:::-;4616:43;;4674:32;4682:8;4692:7;4701:4;;4674:7;:32::i;:::-;4667:4;:39;-1:-1:-1;4467:250:9;;;:::o;1926:129:6:-;1986:7;832:26;532:12;578:3;:16;;2010:4;:20;;2009:40;2001:49;;1926:129;;;:::o;5401:198:3:-;5474:19;;:::i;:::-;5503:22;5528:26;5547:6;5528:18;:26::i;:::-;5567:27;;;;;;;;;;;;;;;;-1:-1:-1;5567:27:3;;5401:198;-1:-1:-1;5401:198:3:o;1393:318:8:-;1511:17;;:::i;:::-;1543:119;;;;;;;;1556:1;1543:119;;;;1565:1;1543:119;;;;1574:4;1543:119;;;;1586:5;1543:119;;;;1599:5;1543:119;;;;1612:44;1635:20;1612:22;:44::i;:::-;1543:119;;1536:126;-1:-1:-1;1668:21:8;1536:126;1681:4;1687:1;1668:6;:21::i;3219:689::-;3310:19;;;;3343;3335:60;;;;;-1:-1:-1;;;3335:60:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;3401:12;3416:29;3429:15;3416:12;:29::i;:::-;3401:44;;3451:22;3476:41;3485:4;3499;:16;;;3491:25;;3476:8;:41::i;:::-;3451:66;;3523:230;3548:15;3530:14;:33;3523:230;;3628:16;;;;;;3611:61;;;;;;;;;;3654:4;3611:61;;;;;;-1:-1:-1;;;3611:61:8;;;;;;22:32:-1;26:21;;;22:32;6:49;;3611:61:8;;;;;;;3592:88;;;;;;;;3573:107;;;;3705:41;;3714:4;;3705:8;:41::i;:::-;3688:58;;3523:230;;;3758:26;;;:43;;;3876:21;;;;3833:70;;3787:14;;3833:13;:70::i;:::-;3807:96;;;-1:-1:-1;;;3219:689:8:o;5465:1033:9:-;5556:20;;5633:5;5666;5556:20;;5752:23;5666:5;5752:21;:23::i;:::-;5744:5;:31;5736:64;;;;;-1:-1:-1;;;5736:64:9;;;;;;;;;;;;-1:-1:-1;;;5736:64:9;;;;;;;;;;;;;;;5858:42;:11;5887:12;5858:42;:28;:42;:::i;:::-;5828:72;-1:-1:-1;5828:72:9;-1:-1:-1;5964:1:9;5943:251;554:1;5967:5;:15;5943:251;;6019:34;:15;6041:11;6019:34;:21;:34;:::i;:::-;6075:15;;;;:8;:15;;;;;;;;:32;;;;;;;;;;-1:-1:-1;6001:52:9;-1:-1:-1;6145:42:9;6075:32;6174:12;6145:42;:28;:42;:::i;:::-;6115:72;-1:-1:-1;6115:72:9;-1:-1:-1;5984:7:9;;5943:251;;;-1:-1:-1;6240:34:9;:15;6262:11;6240:34;:21;:34;:::i;:::-;6225:49;6473:20;;;;;-1:-1:-1;5465:1033:9;;-1:-1:-1;;;;;5465:1033:9:o;1660:199:6:-;1823:31;;;1660:199::o;6087:1736:1:-;6243:11;;:::i;:::-;6262:24;;:::i;:::-;-1:-1:-1;6379:9:1;6399:16;6418:15;:4;:13;:15::i;:::-;6399:34;;6439:18;6460:13;:4;:11;:13::i;:::-;6439:34;;6485:23;6503:4;6485:17;:23::i;:::-;6480:74;;-1:-1:-1;;6525:22:1;;;;;;;;;6530:13;6525:22;;-1:-1:-1;6525:22:1;;;;;-1:-1:-1;6518:29:1;;-1:-1:-1;6518:29:1;6480:74;6583:12;;;;6805:22;;;;;:108;;-1:-1:-1;;;6805:108:1;;-1:-1:-1;;;;;6805:108:1;;;;;;;;;;;;;;6902:4;6805:108;;;;;;6560:20;;6805:45;;;;;;:108;;;;;;;;;;;;;;;:45;:108;;;5:2:-1;;;;30:1;27;20:12;5:2;6805:108:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6805:108:1;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6805:108:1;7045:27;;;;6805:108;;-1:-1:-1;7029:43:1;;7025:95;;;7089:24;;;;;;;;;;7094:15;7089:24;;;;;7111:1;7089:24;;;7082:31;;;;;;;;;7025:95;7297:6;:20;;;7281:13;:36;7277:86;;;7334:22;;;;;;;;;;7339:13;7334:22;;7277:86;7393:22;;:78;;;-1:-1:-1;;;7393:78:1;;-1:-1:-1;;;;;7393:78:1;;;;;;;;;;;;;;;;7369:21;;7393:36;;;;;;;:78;;;;;;;;;;;;;;;:36;:78;;;5:2:-1;;;;30:1;27;20:12;5:2;7393:78:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7393:78:1;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7393:78:1;7633:24;;;;7393:78;;-1:-1:-1;7592:22:1;;7393:78;7633:24;7617:40;;;;;7592:65;;7685:10;7668:14;:27;:66;;;;7715:6;:19;;;7699:13;:35;7668:66;7664:118;;;-1:-1:-1;;7751:24:1;;;;;;;;;7756:15;7751:24;;-1:-1:-1;7751:24:1;;;;;-1:-1:-1;7744:31:1;;-1:-1:-1;;;;;7744:31:1;7664:118;-1:-1:-1;;7794:24:1;;;;;;;;;-1:-1:-1;7794:24:1;;;;;;;;7787:31;-1:-1:-1;;;;;;;;;6087:1736:1:o;7806:514:3:-;7902:10;;;;:17;7947:20;;7977:21;;;7973:314;;8026:11;8016:6;:21;8008:65;;;;;-1:-1:-1;;;8008:65:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;8110:1;8101:10;;8119:25;8147:29;8101:10;8147:18;:29::i;:::-;8119:57;;8184:27;8190:8;8200:4;:10;;;8184:5;:27::i;:::-;8219:10;;;:21;8248:32;;7973:314;8292:23;8298:4;:10;;;8310:4;8292:5;:23::i;2774:232:8:-;2893:19;;;:29;;;;;;;2944:21;;;;2928:73;;2967:33;2981:10;2916:6;2967:13;:33::i;:::-;2928:15;:73::i;1715:201::-;1851:54;;;;;;;;;;;;;;;;;;1889:4;1851:54;;;;;;;;-1:-1:-1;;;1851:54:8;;;;;;22:32:-1;26:21;;;22:32;6:49;;1851:54:8;;;;;;1834:77;;;;;;;1815:16;;:96;1715:201::o;2258:512::-;2557:19;;;;;2419:37;;;2550:40;;;2520:71;;;2629:14;;;;;2622:35;;2597:61;;2738:21;;;;2492:22;;;;2664:101;;2492:22;;2419:37;;2664:21;:101::i;:::-;2258:512;;;;;;:::o;2292:165:6:-;626:19;2428:22;-1:-1:-1;;2405:18:6;;;;2404:47;;2292:165::o;8366:92:0:-;2060:1;8366:92;:::o;6891:97:9:-;6939:4;6982:1;6958:21;:11;:19;:21::i;:::-;:25;6951:32;;6891:97;:::o;346:232:10:-;431:13;;408:7;;423:61;;;;;-1:-1:-1;;;423:61:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;513:13;;490;;506:6;;-1:-1:-1;;513:17:10;;;506:25;;;;;;;;;;;;;;;;537:18;;506:25;;-1:-1:-1;;;537:18:10;;:6;:18;;:::i;:::-;-1:-1:-1;568:5:10;346:232;-1:-1:-1;;346:232:10:o;781:95:7:-;542:18;851:20;;781:95::o;924:91::-;305:1;996:14;;924:91::o;2962:882:2:-;870:19;3567:17;;;775:16;3101:21;;;;3566:32;;;3217:21;;3215:24;3208:31;;;;3812:27;;2962:882::o;10610:351:3:-;10860:4;10854:11;;10720:20;10872:16;;10753:1;10744:10;;;;10758:4;10743:19;10908:24;;10895:38;;10854:11;10610:351::o;4185:578:8:-;4245:7;4275:16;4689:48;4709:5;4701:4;4696:1;:9;;:18;4689:48;;-1:-1:-1;;4724:6:8;4689:48;;;4757:1;4750:8;;4185:578;-1:-1:-1;;4185:578:8:o;4836:136::-;4965:1;4952:9;;;-1:-1:-1;;4951:15:8;4942:25;;4836:136::o;2637:655:5:-;2794:14;2751:19;2814:450;2838:9;:15;;;:22;2834:1;:26;2814:450;;;2875:16;2894:9;:15;;;2910:1;2894:18;;;;;;;;;;;;;;2875:37;;3051:15;3057:8;3051:5;:15::i;:::-;3036:11;:30;3032:226;;3198:21;3210:8;3198:11;:21::i;:::-;3183:36;;;;3032:226;;;3244:5;;;3032:226;-1:-1:-1;2862:3:5;;2814:450;;5078:446:2;5168:12;5219:5;5248:4;870:19;5286:18;;5310:181;5329:17;5317:8;:29;5310:181;;5393:6;;;;;;5356:29;;;;775:16;5417:21;870:19;5466:18;;5310:181;;;-1:-1:-1;;5078:446:2;;;;;:::o;1080:139:7:-;542:18;1182:20;305:1;1163:14;;;;1162:41;;1080:139::o;12470:556:3:-;12646:3;12640:10;12687:4;12679:6;12675:17;12712:6;12706:4;12699:20;12752:4;12746;12742:15;12789:10;12779:8;12775:25;12846:4;12841:3;12837:14;12808:208;12873:3;12863:8;12860:17;12808:208;;;12993:14;;12976:32;;12914:4;12900:19;;;;12939:18;12808:208;;;12812:47;12618:404;;;;;;:::o;13847:379::-;14010:12;;14058:1;14046:14;14088:4;14084:20;;14131:21;;14159:26;;;;14192:24;;13988:234::o;1328:239:5:-;730:19;1520;1447:54;682:16;1447:54;;;;;;;;1553:8;;1328:239::o;2059:574::-;2187:8;2164:20;2201:389;2225:9;:15;;;:22;2221:1;:26;2201:389;;;2262:20;2285:9;:15;;;2301:1;2285:18;;;;;;;;;;;;;;2262:41;;2481:12;2466;:27;2462:122;;;2526:12;2505:9;:15;;;2521:1;2505:18;;;;;;;;;;;;;:33;;;;;2563:12;2548:27;;2462:122;-1:-1:-1;2249:3:5;;2201:389;;;-1:-1:-1;2595:33:5;:9;2615:12;2595:33;:19;:33;:::i;3955:690::-;4135:20;;;;:27;4109:23;4169:472;4193:15;4189:1;:19;4169:472;;;4223:16;4242:14;:20;;;4263:1;4242:23;;;;;;;;;;;;;;4223:42;;4273:21;4297:15;4303:8;4297:5;:15::i;:::-;4273:39;;4467:21;4451:13;:37;4447:188;;;4527:34;;;4598:28;4607:8;4527:34;4598:8;:28::i;:::-;4572:14;:20;;;4593:1;4572:23;;;;;;;;;;;;;:54;;;;;4447:188;;-1:-1:-1;;4210:3:5;;4169:472;;;;3955:690;;;;:::o;1719:115::-;1768:7;730:19;636:12;682:3;:16;;1838:217;682:16;1941:37;;;-1:-1:-1;;1993:41:5;;;;1992:58;;1838:217::o;1096:6729:1:-;;;;;;;;;;-1:-1:-1;;;;;1096:6729:1;;;;;;;;;;;-1:-1:-1;;;;;1096:6729:1;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1096:6729:1;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;1096:6729:1;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://a097e08c247284eeeb2f839db380a28c08c9f606e2628ccf5a226fb836583885
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.