ETH Price: $3,566.86 (+1.75%)
Gas: 34 Gwei

Contract

0xA3748633c6786e1842b5cC44fa43db1ecC710501
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Txn Hash Block From To Value
108689642020-09-15 21:03:511290 days ago1600203831  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BondedSortitionPool

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 13 : BondedSortitionPool.sol
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);
  }
}

File 2 of 13 : IBonding.sol
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);
}

File 3 of 13 : IStaking.sol
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);
}

File 4 of 13 : AbstractSortitionPool.sol
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;
  }
}

File 5 of 13 : RNG.sol
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);
  }
}

File 6 of 13 : DynamicArray.sol
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;
  }
}

File 7 of 13 : GasStation.sol
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);
}

File 8 of 13 : SortitionTree.sol
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;
  }
}

File 9 of 13 : StackLib.sol
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;
  }
}

File 10 of 13 : Branch.sol
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);
  }
}

File 11 of 13 : Position.sol
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);
  }
}

File 12 of 13 : Leaf.sol
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));
  }
}

File 13 of 13 : Interval.sol
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);
      }
    }
  }
}

Settings
{
  "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

Contract ABI

[{"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"}]

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.