Address Details
contract

0xED477A99035d0c1e11369F1D7A4e587893cc002B

Contract Name
AddressSortedLinkedList..hMedian
Creator
0x56fd3f–9b8d81 at 0x3c19b4–b81fd8
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
24451483
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
AddressSortedLinkedListWithMedian




Optimization enabled
true
Compiler version
v0.5.17+commit.d19bba13




Optimization runs
10000
EVM Version
istanbul




Verified at
2023-03-18T11:43:41.739293Z

lib/mento-core/contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

import "./SortedLinkedListWithMedian.sol";

/**
 * @title Maintains a sorted list of unsigned ints keyed by address.
 */
library AddressSortedLinkedListWithMedian {
  using SafeMath for uint256;
  using SortedLinkedListWithMedian for SortedLinkedListWithMedian.List;

  function toBytes(address a) public pure returns (bytes32) {
    return bytes32(uint256(a) << 96);
  }

  function toAddress(bytes32 b) public pure returns (address) {
    return address(uint256(b) >> 96);
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param value The element value.
   * @param lesserKey The key of the element less than the element to insert.
   * @param greaterKey The key of the element greater than the element to insert.
   */
  function insert(
    SortedLinkedListWithMedian.List storage list,
    address key,
    uint256 value,
    address lesserKey,
    address greaterKey
  ) public {
    list.insert(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey));
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(SortedLinkedListWithMedian.List storage list, address key) public {
    list.remove(toBytes(key));
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param value The element value.
   * @param lesserKey The key of the element will be just left of `key` after the update.
   * @param greaterKey The key of the element will be just right of `key` after the update.
   * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction.
   */
  function update(
    SortedLinkedListWithMedian.List storage list,
    address key,
    uint256 value,
    address lesserKey,
    address greaterKey
  ) public {
    list.update(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey));
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(SortedLinkedListWithMedian.List storage list, address key) public view returns (bool) {
    return list.contains(toBytes(key));
  }

  /**
   * @notice Returns the value for a particular key in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return The element value.
   */
  function getValue(SortedLinkedListWithMedian.List storage list, address key) public view returns (uint256) {
    return list.getValue(toBytes(key));
  }

  /**
   * @notice Returns the median value of the sorted list.
   * @param list A storage pointer to the underlying list.
   * @return The median value.
   */
  function getMedianValue(SortedLinkedListWithMedian.List storage list) public view returns (uint256) {
    return list.getValue(list.median);
  }

  /**
   * @notice Returns the key of the first element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the first element in the list.
   */
  function getHead(SortedLinkedListWithMedian.List storage list) external view returns (address) {
    return toAddress(list.getHead());
  }

  /**
   * @notice Returns the key of the median element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the median element in the list.
   */
  function getMedian(SortedLinkedListWithMedian.List storage list) external view returns (address) {
    return toAddress(list.getMedian());
  }

  /**
   * @notice Returns the key of the last element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the last element in the list.
   */
  function getTail(SortedLinkedListWithMedian.List storage list) external view returns (address) {
    return toAddress(list.getTail());
  }

  /**
   * @notice Returns the number of elements in the list.
   * @param list A storage pointer to the underlying list.
   * @return The number of elements in the list.
   */
  function getNumElements(SortedLinkedListWithMedian.List storage list) external view returns (uint256) {
    return list.getNumElements();
  }

  /**
   * @notice Gets all elements from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return Array of all keys in the list.
   * @return Values corresponding to keys, which will be ordered largest to smallest.
   * @return Array of relations to median of corresponding list elements.
   */
  function getElements(SortedLinkedListWithMedian.List storage list)
    public
    view
    returns (
      address[] memory,
      uint256[] memory,
      SortedLinkedListWithMedian.MedianRelation[] memory
    )
  {
    bytes32[] memory byteKeys = list.getKeys();
    address[] memory keys = new address[](byteKeys.length);
    uint256[] memory values = new uint256[](byteKeys.length);
    // prettier-ignore
    SortedLinkedListWithMedian.MedianRelation[] memory relations =
      new SortedLinkedListWithMedian.MedianRelation[](keys.length);
    for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) {
      keys[i] = toAddress(byteKeys[i]);
      values[i] = list.getValue(byteKeys[i]);
      relations[i] = list.relation[byteKeys[i]];
    }
    return (keys, values, relations);
  }
}
        

/lib/mento-core/contracts/common/linkedlists/LinkedList.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @title Maintains a doubly linked list keyed by bytes32.
 * @dev Following the `next` pointers will lead you to the head, rather than the tail.
 */
library LinkedList {
  using SafeMath for uint256;

  struct Element {
    bytes32 previousKey;
    bytes32 nextKey;
    bool exists;
  }

  struct List {
    bytes32 head;
    bytes32 tail;
    uint256 numElements;
    mapping(bytes32 => Element) elements;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param previousKey The key of the element that comes before the element to insert.
   * @param nextKey The key of the element that comes after the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    bytes32 previousKey,
    bytes32 nextKey
  ) internal {
    require(key != bytes32(0), "Key must be defined");
    require(!contains(list, key), "Can't insert an existing element");
    require(previousKey != key && nextKey != key, "Key cannot be the same as previousKey or nextKey");

    Element storage element = list.elements[key];
    element.exists = true;

    if (list.numElements == 0) {
      list.tail = key;
      list.head = key;
    } else {
      require(previousKey != bytes32(0) || nextKey != bytes32(0), "Either previousKey or nextKey must be defined");

      element.previousKey = previousKey;
      element.nextKey = nextKey;

      if (previousKey != bytes32(0)) {
        require(contains(list, previousKey), "If previousKey is defined, it must exist in the list");
        Element storage previousElement = list.elements[previousKey];
        require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey");
        previousElement.nextKey = key;
      } else {
        list.tail = key;
      }

      if (nextKey != bytes32(0)) {
        require(contains(list, nextKey), "If nextKey is defined, it must exist in the list");
        Element storage nextElement = list.elements[nextKey];
        require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey");
        nextElement.previousKey = key;
      } else {
        list.head = key;
      }
    }

    list.numElements = list.numElements.add(1);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, bytes32(0), list.tail);
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    Element storage element = list.elements[key];
    require(key != bytes32(0) && contains(list, key), "key not in list");
    if (element.previousKey != bytes32(0)) {
      Element storage previousElement = list.elements[element.previousKey];
      previousElement.nextKey = element.nextKey;
    } else {
      list.tail = element.nextKey;
    }

    if (element.nextKey != bytes32(0)) {
      Element storage nextElement = list.elements[element.nextKey];
      nextElement.previousKey = element.previousKey;
    } else {
      list.head = element.previousKey;
    }

    delete list.elements[key];
    list.numElements = list.numElements.sub(1);
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param previousKey The key of the element that comes before the updated element.
   * @param nextKey The key of the element that comes after the updated element.
   */
  function update(
    List storage list,
    bytes32 key,
    bytes32 previousKey,
    bytes32 nextKey
  ) internal {
    require(key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key), "key on in list");
    remove(list, key);
    insert(list, key, previousKey, nextKey);
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.elements[key].exists;
  }

  /**
   * @notice Returns the keys of the N elements at the head of the list.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to return.
   * @return The keys of the N elements at the head of the list.
   * @dev Reverts if n is greater than the number of elements in the list.
   */
  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {
    require(n <= list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    bytes32 key = list.head;
    for (uint256 i = 0; i < n; i = i.add(1)) {
      keys[i] = key;
      key = list.elements[key].previousKey;
    }
    return keys;
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return headN(list, list.numElements);
  }
}
          

/lib/mento-core/contracts/common/linkedlists/SortedLinkedList.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./LinkedList.sol";

/**
 * @title Maintains a sorted list of unsigned ints keyed by bytes32.
 */
library SortedLinkedList {
  using SafeMath for uint256;
  using LinkedList for LinkedList.List;

  struct List {
    LinkedList.List list;
    mapping(bytes32 => uint256) values;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param value The element value.
   * @param lesserKey The key of the element less than the element to insert.
   * @param greaterKey The key of the element greater than the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    require(key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key), "invalid key");
    require(
      (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0,
      "greater and lesser key zero"
    );
    require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key");
    require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key");
    (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey);
    list.list.insert(key, lesserKey, greaterKey);
    list.values[key] = value;
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    list.list.remove(key);
    list.values[key] = 0;
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param value The element value.
   * @param lesserKey The key of the element will be just left of `key` after the update.
   * @param greaterKey The key of the element will be just right of `key` after the update.
   * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction.
   */
  function update(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    remove(list, key);
    insert(list, key, value, lesserKey, greaterKey);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, 0, bytes32(0), list.list.tail);
  }

  /**
   * @notice Removes N elements from the head of the list and returns their keys.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to pop.
   * @return The keys of the popped elements.
   */
  function popN(List storage list, uint256 n) internal returns (bytes32[] memory) {
    require(n <= list.list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    for (uint256 i = 0; i < n; i = i.add(1)) {
      bytes32 key = list.list.head;
      keys[i] = key;
      remove(list, key);
    }
    return keys;
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.list.contains(key);
  }

  /**
   * @notice Returns the value for a particular key in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return The element value.
   */
  function getValue(List storage list, bytes32 key) internal view returns (uint256) {
    return list.values[key];
  }

  /**
   * @notice Gets all elements from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return Array of all keys in the list.
   * @return Values corresponding to keys, which will be ordered largest to smallest.
   */
  function getElements(List storage list) internal view returns (bytes32[] memory, uint256[] memory) {
    bytes32[] memory keys = getKeys(list);
    uint256[] memory values = new uint256[](keys.length);
    for (uint256 i = 0; i < keys.length; i = i.add(1)) {
      values[i] = list.values[keys[i]];
    }
    return (keys, values);
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return list.list.getKeys();
  }

  /**
   * @notice Returns first N greatest elements of the list.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to return.
   * @return The keys of the first n elements.
   * @dev Reverts if n is greater than the number of elements in the list.
   */
  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {
    return list.list.headN(n);
  }

  /**
   * @notice Returns the keys of the elements greaterKey than and less than the provided value.
   * @param list A storage pointer to the underlying list.
   * @param value The element value.
   * @param lesserKey The key of the element which could be just left of the new value.
   * @param greaterKey The key of the element which could be just right of the new value.
   * @return The correct lesserKey keys.
   * @return The correct greaterKey keys.
   */
  function getLesserAndGreater(
    List storage list,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) private view returns (bytes32, bytes32) {
    // Check for one of the following conditions and fail if none are met:
    //   1. The value is less than the current lowest value
    //   2. The value is greater than the current greatest value
    //   3. The value is just greater than the value for `lesserKey`
    //   4. The value is just less than the value for `greaterKey`
    if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) {
      return (lesserKey, list.list.tail);
    } else if (greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)) {
      return (list.list.head, greaterKey);
    } else if (
      lesserKey != bytes32(0) && isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey)
    ) {
      return (lesserKey, list.list.elements[lesserKey].nextKey);
    } else if (
      greaterKey != bytes32(0) && isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey)
    ) {
      return (list.list.elements[greaterKey].previousKey, greaterKey);
    } else {
      require(false, "get lesser and greater failure");
    }
  }

  /**
   * @notice Returns whether or not a given element is between two other elements.
   * @param list A storage pointer to the underlying list.
   * @param value The element value.
   * @param lesserKey The key of the element whose value should be lesserKey.
   * @param greaterKey The key of the element whose value should be greaterKey.
   * @return True if the given element is between the two other elements.
   */
  function isValueBetween(
    List storage list,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) private view returns (bool) {
    bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value;
    bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value;
    return isLesser && isGreater;
  }
}
          

/lib/mento-core/contracts/common/linkedlists/SortedLinkedListWithMedian.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./LinkedList.sol";
import "./SortedLinkedList.sol";

/**
 * @title Maintains a sorted list of unsigned ints keyed by bytes32.
 */
library SortedLinkedListWithMedian {
  using SafeMath for uint256;
  using SortedLinkedList for SortedLinkedList.List;

  enum MedianAction {
    None,
    Lesser,
    Greater
  }

  enum MedianRelation {
    Undefined,
    Lesser,
    Greater,
    Equal
  }

  struct List {
    SortedLinkedList.List list;
    bytes32 median;
    mapping(bytes32 => MedianRelation) relation;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param value The element value.
   * @param lesserKey The key of the element less than the element to insert.
   * @param greaterKey The key of the element greater than the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    list.list.insert(key, value, lesserKey, greaterKey);
    LinkedList.Element storage element = list.list.list.elements[key];

    MedianAction action = MedianAction.None;
    if (list.list.list.numElements == 1) {
      list.median = key;
      list.relation[key] = MedianRelation.Equal;
    } else if (list.list.list.numElements % 2 == 1) {
      // When we have an odd number of elements, and the element that we inserted is less than
      // the previous median, we need to slide the median down one element, since we had previously
      // selected the greater of the two middle elements.
      if (element.previousKey == bytes32(0) || list.relation[element.previousKey] == MedianRelation.Lesser) {
        action = MedianAction.Lesser;
        list.relation[key] = MedianRelation.Lesser;
      } else {
        list.relation[key] = MedianRelation.Greater;
      }
    } else {
      // When we have an even number of elements, and the element that we inserted is greater than
      // the previous median, we need to slide the median up one element, since we always select
      // the greater of the two middle elements.
      if (element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater) {
        action = MedianAction.Greater;
        list.relation[key] = MedianRelation.Greater;
      } else {
        list.relation[key] = MedianRelation.Lesser;
      }
    }
    updateMedian(list, action);
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    MedianAction action = MedianAction.None;
    if (list.list.list.numElements == 0) {
      list.median = bytes32(0);
    } else if (list.list.list.numElements % 2 == 0) {
      // When we have an even number of elements, we always choose the higher of the two medians.
      // Thus, if the element we're removing is greaterKey than or equal to the median we need to
      // slide the median left by one.
      if (list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal) {
        action = MedianAction.Lesser;
      }
    } else {
      // When we don't have an even number of elements, we just choose the median value.
      // Thus, if the element we're removing is less than or equal to the median, we need to slide
      // median right by one.
      if (list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal) {
        action = MedianAction.Greater;
      }
    }
    updateMedian(list, action);

    list.list.remove(key);
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param value The element value.
   * @param lesserKey The key of the element will be just left of `key` after the update.
   * @param greaterKey The key of the element will be just right of `key` after the update.
   * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction.
   */
  function update(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    remove(list, key);
    insert(list, key, value, lesserKey, greaterKey);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, 0, bytes32(0), list.list.list.tail);
  }

  /**
   * @notice Removes N elements from the head of the list and returns their keys.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to pop.
   * @return The keys of the popped elements.
   */
  function popN(List storage list, uint256 n) internal returns (bytes32[] memory) {
    require(n <= list.list.list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    for (uint256 i = 0; i < n; i = i.add(1)) {
      bytes32 key = list.list.list.head;
      keys[i] = key;
      remove(list, key);
    }
    return keys;
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.list.contains(key);
  }

  /**
   * @notice Returns the value for a particular key in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return The element value.
   */
  function getValue(List storage list, bytes32 key) internal view returns (uint256) {
    return list.list.values[key];
  }

  /**
   * @notice Returns the median value of the sorted list.
   * @param list A storage pointer to the underlying list.
   * @return The median value.
   */
  function getMedianValue(List storage list) internal view returns (uint256) {
    return getValue(list, list.median);
  }

  /**
   * @notice Returns the key of the first element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the first element in the list.
   */
  function getHead(List storage list) internal view returns (bytes32) {
    return list.list.list.head;
  }

  /**
   * @notice Returns the key of the median element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the median element in the list.
   */
  function getMedian(List storage list) internal view returns (bytes32) {
    return list.median;
  }

  /**
   * @notice Returns the key of the last element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the last element in the list.
   */
  function getTail(List storage list) internal view returns (bytes32) {
    return list.list.list.tail;
  }

  /**
   * @notice Returns the number of elements in the list.
   * @param list A storage pointer to the underlying list.
   * @return The number of elements in the list.
   */
  function getNumElements(List storage list) internal view returns (uint256) {
    return list.list.list.numElements;
  }

  /**
   * @notice Gets all elements from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return Array of all keys in the list.
   * @return Values corresponding to keys, which will be ordered largest to smallest.
   * @return Array of relations to median of corresponding list elements.
   */
  function getElements(List storage list)
    internal
    view
    returns (
      bytes32[] memory,
      uint256[] memory,
      MedianRelation[] memory
    )
  {
    bytes32[] memory keys = getKeys(list);
    uint256[] memory values = new uint256[](keys.length);
    MedianRelation[] memory relations = new MedianRelation[](keys.length);
    for (uint256 i = 0; i < keys.length; i = i.add(1)) {
      values[i] = list.list.values[keys[i]];
      relations[i] = list.relation[keys[i]];
    }
    return (keys, values, relations);
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return list.list.getKeys();
  }

  /**
   * @notice Moves the median pointer right or left of its current value.
   * @param list A storage pointer to the underlying list.
   * @param action Which direction to move the median pointer.
   */
  function updateMedian(List storage list, MedianAction action) private {
    LinkedList.Element storage previousMedian = list.list.list.elements[list.median];
    if (action == MedianAction.Lesser) {
      list.relation[list.median] = MedianRelation.Greater;
      list.median = previousMedian.previousKey;
    } else if (action == MedianAction.Greater) {
      list.relation[list.median] = MedianRelation.Lesser;
      list.median = previousMedian.nextKey;
    }
    list.relation[list.median] = MedianRelation.Equal;
  }
}
          

/lib/mento-core/lib/openzeppelin-contracts/contracts/math/SafeMath.sol

pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}
          

Contract ABI

[{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"toAddress","inputs":[{"type":"bytes32","name":"b","internalType":"bytes32"}],"constant":true},{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"toBytes","inputs":[{"type":"address","name":"a","internalType":"address"}],"constant":true}]
              

Contract Creation Code

0x611673610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100e95760003560e01c80636eafa6c31161009657806395073a791161007057806395073a791461037f578063c1e728e9146103cc578063d4a0927214610412578063d938ec7b1461046e576100e9565b80636eafa6c3146102cb5780637c6bb862146102e8578063832a214714610321576100e9565b8063593b79fe116100c7578063593b79fe1461016e57806359d556a8146101b35780636cfa3873146101d0576100e9565b80630944c594146100ee5780633118159e14610134578063341f662314610151575b600080fd5b61010b6004803603602081101561010457600080fd5b503561048b565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61010b6004803603602081101561014a57600080fd5b50356104a4565b61010b6004803603602081101561016757600080fd5b50356104b2565b6101a16004803603602081101561018457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166104b8565b60408051918252519081900360200190f35b6101a1600480360360208110156101c957600080fd5b50356104e0565b6101ed600480360360208110156101e657600080fd5b50356104f9565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561023557818101518382015260200161021d565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561027457818101518382015260200161025c565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156102b357818101518382015260200161029b565b50505050905001965050505050505060405180910390f35b6101a1600480360360208110156102e157600080fd5b50356106d2565b6101a1600480360360408110156102fe57600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff166106dd565b81801561032d57600080fd5b5061037d600480360360a081101561034457600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff6020820135811691604081013591606082013581169160800135166106ff565b005b6103b86004803603604081101561039557600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff16610735565b604080519115158252519081900360200190f35b8180156103d857600080fd5b5061037d600480360360408110156103ef57600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff16610750565b81801561041e57600080fd5b5061037d600480360360a081101561043557600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff60208201358116916040810135916060820135811691608001351661076d565b61010b6004803603602081101561048457600080fd5b503561079c565b600061049e610499836107aa565b6104b2565b92915050565b600061049e610499836107ae565b60601c90565b60601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690565b600061049e8260050154836107b590919063ffffffff16565b606080606080610508856107cb565b905060608151604051908082528060200260200182016040528015610537578160200160208202803883390190505b50905060608251604051908082528060200260200182016040528015610567578160200160208202803883390190505b50905060608251604051908082528060200260200182016040528015610597578160200160208202803883390190505b50905060005b84518110156106c3576105c28582815181106105b557fe5b60200260200101516104b2565b8482815181106105ce57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061062e85828151811061061757fe5b60200260200101518a6107b590919063ffffffff16565b83828151811061063a57fe5b60200260200101818152505088600601600086838151811061065857fe5b6020026020010151815260200190815260200160002060009054906101000a900460ff1682828151811061068857fe5b6020026020010190600381111561069b57fe5b908160038111156106a857fe5b9052506106bc81600163ffffffff6107d616565b905061059d565b50919790965090945092505050565b600061049e82610830565b60006106f86106eb836104b8565b849063ffffffff6107b516565b9392505050565b61072e61070b856104b8565b84610715856104b8565b61071e856104b8565b899392919063ffffffff61083716565b5050505050565b60006106f8610743836104b8565b849063ffffffff61084e16565b61076961075c826104b8565b839063ffffffff61086016565b5050565b61072e610779856104b8565b84610783856104b8565b61078c856104b8565b899392919063ffffffff61094f16565b600061049e61049983610aca565b5490565b6005015490565b6000908152600491909101602052604090205490565b606061049e82610ad1565b6000828201838110156106f8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6002015490565b6108418585610860565b61072e858585858561094f565b60006106f8838363ffffffff610adc16565b60028201546000906108785760006005840155610930565b600283810154066108dc576002600083815260068501602052604090205460ff1660038111156108a457fe5b14806108ce57506003600083815260068501602052604090205460ff1660038111156108cc57fe5b145b156108d7575060015b610930565b6001600083815260068501602052604090205460ff1660038111156108fd57fe5b148061092757506003600083815260068501602052604090205460ff16600381111561092557fe5b145b15610930575060025b61093a8382610aee565b61094a838363ffffffff610ba416565b505050565b610962858585858563ffffffff610bc816565b600084815260038601602052604081206002870154909190600114156109b157600587018690556000868152600688016020526040902080546003919060ff19166001835b0217905550610ab7565b6002878101540660011415610a3e57815415806109ee575060018254600090815260068901602052604090205460ff1660038111156109ec57fe5b145b15610a17575060008581526006870160205260409020805460ff19166001908117909155610a39565b6000868152600688016020526040902080546002919060ff19166001836109a7565b610ab7565b60018201541580610a72575060026001830154600090815260068901602052604090205460ff166003811115610a7057fe5b145b15610a9b5750600085815260068701602052604090208054600291829160ff19166001836109a7565b60008681526006880160205260409020805460ff191660011790555b610ac18782610aee565b50505050505050565b6001015490565b606061049e82610db3565b60006106f8838363ffffffff610dc316565b6005820154600090815260038301602052604090206001826002811115610b1157fe5b1415610b415760058301805460009081526006850160205260409020805460ff1916600217905581549055610b7f565b6002826002811115610b4f57fe5b1415610b7f5760058301805460009081526006850160205260409020805460ff1916600190811790915582015490555b505060058101546000908152600690910160205260409020805460ff19166003179055565b610bb4828263ffffffff610ddf16565b600090815260049091016020526040812055565b8315801590610bd75750818414155b8015610be35750808414155b8015610bf65750610bf48585610adc565b155b610c47576040805162461bcd60e51b815260206004820152600b60248201527f696e76616c6964206b6579000000000000000000000000000000000000000000604482015290519081900360640190fd5b81151580610c5457508015155b80610c6157506002850154155b610cb2576040805162461bcd60e51b815260206004820152601b60248201527f6772656174657220616e64206c6573736572206b6579207a65726f0000000000604482015290519081900360640190fd5b610cbc8583610adc565b80610cc5575081155b610d16576040805162461bcd60e51b815260206004820152601260248201527f696e76616c6964206c6573736572206b65790000000000000000000000000000604482015290519081900360640190fd5b610d208582610adc565b80610d29575080155b610d7a576040805162461bcd60e51b815260206004820152601360248201527f696e76616c69642067726561746572206b657900000000000000000000000000604482015290519081900360640190fd5b610d8685848484610efb565b9092509050610d9d8585848463ffffffff61104116565b5050600091825260049092016020526040902055565b606061049e82836002015461133d565b6000908152600391909101602052604090206002015460ff1690565b600081815260038301602052604090208115801590610e035750610e038383610dc3565b610e54576040805162461bcd60e51b815260206004820152600f60248201527f6b6579206e6f7420696e206c6973740000000000000000000000000000000000604482015290519081900360640190fd5b805415610e7b57805460009081526003840160205260409020600180830154910155610e86565b600180820154908401555b600181015415610eae5760018101546000908152600384016020526040902081549055610eb3565b805483555b600082815260038401602052604081208181556001808201929092556002908101805460ff19169055840154610eee9163ffffffff61142516565b8360020181905550505050565b60008083158015610f1a5750610f1a8686868960000160010154611467565b15610f2d57505060018401548290611038565b82158015610f4657508554610f46908790879086611467565b15610f55575050835481611038565b8315801590610f8257506000848152600387016020526040902060010154610f8290879087908790611467565b15610fa457505060008281526003850160205260409020600101548290611038565b8215801590610fcd57506000838152600387016020526040902054610fcd908790879086611467565b15610feb575050600081815260038501602052604090205481611038565b6040805162461bcd60e51b815260206004820152601e60248201527f676574206c657373657220616e642067726561746572206661696c7572650000604482015290519081900360640190fd5b94509492505050565b82611093576040805162461bcd60e51b815260206004820152601360248201527f4b6579206d75737420626520646566696e656400000000000000000000000000604482015290519081900360640190fd5b61109d8484610dc3565b156110ef576040805162461bcd60e51b815260206004820181905260248201527f43616e277420696e7365727420616e206578697374696e6720656c656d656e74604482015290519081900360640190fd5b8282141580156110ff5750828114155b61113a5760405162461bcd60e51b81526004018080602001828103825260308152602001806115576030913960400191505060405180910390fd5b600083815260038501602052604090206002808201805460ff191660011790558501546111705760018501849055838555611318565b8215158061117d57508115155b6111b85760405162461bcd60e51b815260040180806020018281038252602d815260200180611612602d913960400191505060405180910390fd5b82815560018101829055821561126a576111d28584610dc3565b61120d5760405162461bcd60e51b81526004018080602001828103825260348152602001806115ae6034913960400191505060405180910390fd5b600083815260038601602052604090206001810154831461125f5760405162461bcd60e51b81526004018080602001828103825260278152602001806115876027913960400191505060405180910390fd5b600101849055611272565b600185018490555b8115611314576112828583610dc3565b6112bd5760405162461bcd60e51b81526004018080602001828103825260308152602001806115e26030913960400191505060405180910390fd5b600082815260038601602052604090208054841461130c5760405162461bcd60e51b81526004018080602001828103825260278152602001806115876027913960400191505060405180910390fd5b849055611318565b8385555b600285015461132e90600163ffffffff6107d616565b85600201819055505050505050565b60608260020154821115611398576040805162461bcd60e51b815260206004820152601360248201527f6e6f7420656e6f75676820656c656d656e747300000000000000000000000000604482015290519081900360640190fd5b6060826040519080825280602002602001820160405280156113c4578160200160208202803883390190505b50845490915060005b8481101561141b57818382815181106113e257fe5b60209081029190910181019190915260009283526003870190526040909120549061141481600163ffffffff6107d616565b90506113cd565b5090949350505050565b60006106f883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506114bf565b600080831580611487575060008481526004870160205260409020548510155b905060008315806114a8575060008481526004880160205260409020548611155b90508180156114b45750805b979650505050505050565b6000818484111561154e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115135781810151838201526020016114fb565b50505050905090810190601f1680156115405780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505090039056fe4b65792063616e6e6f74206265207468652073616d652061732070726576696f75734b6579206f72206e6578744b657970726576696f75734b6579206d7573742062652061646a6163656e7420746f206e6578744b657949662070726576696f75734b657920697320646566696e65642c206974206d75737420657869737420696e20746865206c6973744966206e6578744b657920697320646566696e65642c206974206d75737420657869737420696e20746865206c6973744569746865722070726576696f75734b6579206f72206e6578744b6579206d75737420626520646566696e6564a265627a7a72315820544502d56ff80b5fcc5450bae91086f72493a0693dc0e940bcb8d03e451f915864736f6c63430005110032

Deployed ByteCode

0x73ed477a99035d0c1e11369f1d7a4e587893cc002b30146080604052600436106100e95760003560e01c80636eafa6c31161009657806395073a791161007057806395073a791461037f578063c1e728e9146103cc578063d4a0927214610412578063d938ec7b1461046e576100e9565b80636eafa6c3146102cb5780637c6bb862146102e8578063832a214714610321576100e9565b8063593b79fe116100c7578063593b79fe1461016e57806359d556a8146101b35780636cfa3873146101d0576100e9565b80630944c594146100ee5780633118159e14610134578063341f662314610151575b600080fd5b61010b6004803603602081101561010457600080fd5b503561048b565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61010b6004803603602081101561014a57600080fd5b50356104a4565b61010b6004803603602081101561016757600080fd5b50356104b2565b6101a16004803603602081101561018457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166104b8565b60408051918252519081900360200190f35b6101a1600480360360208110156101c957600080fd5b50356104e0565b6101ed600480360360208110156101e657600080fd5b50356104f9565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561023557818101518382015260200161021d565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561027457818101518382015260200161025c565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156102b357818101518382015260200161029b565b50505050905001965050505050505060405180910390f35b6101a1600480360360208110156102e157600080fd5b50356106d2565b6101a1600480360360408110156102fe57600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff166106dd565b81801561032d57600080fd5b5061037d600480360360a081101561034457600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff6020820135811691604081013591606082013581169160800135166106ff565b005b6103b86004803603604081101561039557600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff16610735565b604080519115158252519081900360200190f35b8180156103d857600080fd5b5061037d600480360360408110156103ef57600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff16610750565b81801561041e57600080fd5b5061037d600480360360a081101561043557600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff60208201358116916040810135916060820135811691608001351661076d565b61010b6004803603602081101561048457600080fd5b503561079c565b600061049e610499836107aa565b6104b2565b92915050565b600061049e610499836107ae565b60601c90565b60601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690565b600061049e8260050154836107b590919063ffffffff16565b606080606080610508856107cb565b905060608151604051908082528060200260200182016040528015610537578160200160208202803883390190505b50905060608251604051908082528060200260200182016040528015610567578160200160208202803883390190505b50905060608251604051908082528060200260200182016040528015610597578160200160208202803883390190505b50905060005b84518110156106c3576105c28582815181106105b557fe5b60200260200101516104b2565b8482815181106105ce57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061062e85828151811061061757fe5b60200260200101518a6107b590919063ffffffff16565b83828151811061063a57fe5b60200260200101818152505088600601600086838151811061065857fe5b6020026020010151815260200190815260200160002060009054906101000a900460ff1682828151811061068857fe5b6020026020010190600381111561069b57fe5b908160038111156106a857fe5b9052506106bc81600163ffffffff6107d616565b905061059d565b50919790965090945092505050565b600061049e82610830565b60006106f86106eb836104b8565b849063ffffffff6107b516565b9392505050565b61072e61070b856104b8565b84610715856104b8565b61071e856104b8565b899392919063ffffffff61083716565b5050505050565b60006106f8610743836104b8565b849063ffffffff61084e16565b61076961075c826104b8565b839063ffffffff61086016565b5050565b61072e610779856104b8565b84610783856104b8565b61078c856104b8565b899392919063ffffffff61094f16565b600061049e61049983610aca565b5490565b6005015490565b6000908152600491909101602052604090205490565b606061049e82610ad1565b6000828201838110156106f8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6002015490565b6108418585610860565b61072e858585858561094f565b60006106f8838363ffffffff610adc16565b60028201546000906108785760006005840155610930565b600283810154066108dc576002600083815260068501602052604090205460ff1660038111156108a457fe5b14806108ce57506003600083815260068501602052604090205460ff1660038111156108cc57fe5b145b156108d7575060015b610930565b6001600083815260068501602052604090205460ff1660038111156108fd57fe5b148061092757506003600083815260068501602052604090205460ff16600381111561092557fe5b145b15610930575060025b61093a8382610aee565b61094a838363ffffffff610ba416565b505050565b610962858585858563ffffffff610bc816565b600084815260038601602052604081206002870154909190600114156109b157600587018690556000868152600688016020526040902080546003919060ff19166001835b0217905550610ab7565b6002878101540660011415610a3e57815415806109ee575060018254600090815260068901602052604090205460ff1660038111156109ec57fe5b145b15610a17575060008581526006870160205260409020805460ff19166001908117909155610a39565b6000868152600688016020526040902080546002919060ff19166001836109a7565b610ab7565b60018201541580610a72575060026001830154600090815260068901602052604090205460ff166003811115610a7057fe5b145b15610a9b5750600085815260068701602052604090208054600291829160ff19166001836109a7565b60008681526006880160205260409020805460ff191660011790555b610ac18782610aee565b50505050505050565b6001015490565b606061049e82610db3565b60006106f8838363ffffffff610dc316565b6005820154600090815260038301602052604090206001826002811115610b1157fe5b1415610b415760058301805460009081526006850160205260409020805460ff1916600217905581549055610b7f565b6002826002811115610b4f57fe5b1415610b7f5760058301805460009081526006850160205260409020805460ff1916600190811790915582015490555b505060058101546000908152600690910160205260409020805460ff19166003179055565b610bb4828263ffffffff610ddf16565b600090815260049091016020526040812055565b8315801590610bd75750818414155b8015610be35750808414155b8015610bf65750610bf48585610adc565b155b610c47576040805162461bcd60e51b815260206004820152600b60248201527f696e76616c6964206b6579000000000000000000000000000000000000000000604482015290519081900360640190fd5b81151580610c5457508015155b80610c6157506002850154155b610cb2576040805162461bcd60e51b815260206004820152601b60248201527f6772656174657220616e64206c6573736572206b6579207a65726f0000000000604482015290519081900360640190fd5b610cbc8583610adc565b80610cc5575081155b610d16576040805162461bcd60e51b815260206004820152601260248201527f696e76616c6964206c6573736572206b65790000000000000000000000000000604482015290519081900360640190fd5b610d208582610adc565b80610d29575080155b610d7a576040805162461bcd60e51b815260206004820152601360248201527f696e76616c69642067726561746572206b657900000000000000000000000000604482015290519081900360640190fd5b610d8685848484610efb565b9092509050610d9d8585848463ffffffff61104116565b5050600091825260049092016020526040902055565b606061049e82836002015461133d565b6000908152600391909101602052604090206002015460ff1690565b600081815260038301602052604090208115801590610e035750610e038383610dc3565b610e54576040805162461bcd60e51b815260206004820152600f60248201527f6b6579206e6f7420696e206c6973740000000000000000000000000000000000604482015290519081900360640190fd5b805415610e7b57805460009081526003840160205260409020600180830154910155610e86565b600180820154908401555b600181015415610eae5760018101546000908152600384016020526040902081549055610eb3565b805483555b600082815260038401602052604081208181556001808201929092556002908101805460ff19169055840154610eee9163ffffffff61142516565b8360020181905550505050565b60008083158015610f1a5750610f1a8686868960000160010154611467565b15610f2d57505060018401548290611038565b82158015610f4657508554610f46908790879086611467565b15610f55575050835481611038565b8315801590610f8257506000848152600387016020526040902060010154610f8290879087908790611467565b15610fa457505060008281526003850160205260409020600101548290611038565b8215801590610fcd57506000838152600387016020526040902054610fcd908790879086611467565b15610feb575050600081815260038501602052604090205481611038565b6040805162461bcd60e51b815260206004820152601e60248201527f676574206c657373657220616e642067726561746572206661696c7572650000604482015290519081900360640190fd5b94509492505050565b82611093576040805162461bcd60e51b815260206004820152601360248201527f4b6579206d75737420626520646566696e656400000000000000000000000000604482015290519081900360640190fd5b61109d8484610dc3565b156110ef576040805162461bcd60e51b815260206004820181905260248201527f43616e277420696e7365727420616e206578697374696e6720656c656d656e74604482015290519081900360640190fd5b8282141580156110ff5750828114155b61113a5760405162461bcd60e51b81526004018080602001828103825260308152602001806115576030913960400191505060405180910390fd5b600083815260038501602052604090206002808201805460ff191660011790558501546111705760018501849055838555611318565b8215158061117d57508115155b6111b85760405162461bcd60e51b815260040180806020018281038252602d815260200180611612602d913960400191505060405180910390fd5b82815560018101829055821561126a576111d28584610dc3565b61120d5760405162461bcd60e51b81526004018080602001828103825260348152602001806115ae6034913960400191505060405180910390fd5b600083815260038601602052604090206001810154831461125f5760405162461bcd60e51b81526004018080602001828103825260278152602001806115876027913960400191505060405180910390fd5b600101849055611272565b600185018490555b8115611314576112828583610dc3565b6112bd5760405162461bcd60e51b81526004018080602001828103825260308152602001806115e26030913960400191505060405180910390fd5b600082815260038601602052604090208054841461130c5760405162461bcd60e51b81526004018080602001828103825260278152602001806115876027913960400191505060405180910390fd5b849055611318565b8385555b600285015461132e90600163ffffffff6107d616565b85600201819055505050505050565b60608260020154821115611398576040805162461bcd60e51b815260206004820152601360248201527f6e6f7420656e6f75676820656c656d656e747300000000000000000000000000604482015290519081900360640190fd5b6060826040519080825280602002602001820160405280156113c4578160200160208202803883390190505b50845490915060005b8481101561141b57818382815181106113e257fe5b60209081029190910181019190915260009283526003870190526040909120549061141481600163ffffffff6107d616565b90506113cd565b5090949350505050565b60006106f883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506114bf565b600080831580611487575060008481526004870160205260409020548510155b905060008315806114a8575060008481526004880160205260409020548611155b90508180156114b45750805b979650505050505050565b6000818484111561154e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115135781810151838201526020016114fb565b50505050905090810190601f1680156115405780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505090039056fe4b65792063616e6e6f74206265207468652073616d652061732070726576696f75734b6579206f72206e6578744b657970726576696f75734b6579206d7573742062652061646a6163656e7420746f206e6578744b657949662070726576696f75734b657920697320646566696e65642c206974206d75737420657869737420696e20746865206c6973744966206e6578744b657920697320646566696e65642c206974206d75737420657869737420696e20746865206c6973744569746865722070726576696f75734b6579206f72206e6578744b6579206d75737420626520646566696e6564a265627a7a72315820544502d56ff80b5fcc5450bae91086f72493a0693dc0e940bcb8d03e451f915864736f6c63430005110032

External libraries