false
false
0

Contract Address Details

0x35e72B82793C5Bb8cE794FcE6349d459e4149765

Contract Name
FluxAggregator
Creator
0xbb78ef–16399b at 0x5d2c6a–10bdad
Balance
0 FTN ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
4346876
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
FluxAggregator




Optimization enabled
true
Compiler version
v0.8.6+commit.11564f7e




Optimization runs
200
EVM Version
default




Verified at
2024-12-16T20:10:47.904579Z

Constructor Arguments

000000000000000000000000000000000000000000000000000009184e72a0000000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016e360000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000185052494345204645454420555344432f55534420544553540000000000000000

Arg [0] (uint128) : 10000000000000
Arg [1] (uint32) : 4000
Arg [2] (int256) : 0
Arg [3] (int256) : 1500000
Arg [4] (uint8) : 8
Arg [5] (string) : PRICE FEED USDC/USD TEST

              

contracts/FluxAggregator.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "./interfaces/AggregatorValidatorInterface.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./interfaces/AggregatorV2V3Interface.sol";
import "./Median.sol";

/**
 * @title The Prepaid Aggregator contract
 * @notice Handles aggregating data pushed in from off-chain, and unlocks
 * payment for oracles as they report. Oracles' submissions are gathered in
 * rounds, with each round aggregating the submissions for each oracle into a
 * single answer. The latest aggregated answer is exposed as well as historical
 * answers and their updated at timestamp.
 */
contract FluxAggregator is AggregatorV2V3Interface, AccessControl {
  struct Round {
    int256 answer;
    uint64 startedAt;
    uint64 updatedAt;
    uint32 answeredInRound;
  }

  struct RoundDetails {
    int256[] submissions;
    uint32 maxSubmissions;
    uint32 minSubmissions;
    uint32 timeout;
    uint128 paymentAmount;
  }

  struct OracleStatus {
    uint128 withdrawable;
    uint32 startingRound;
    uint32 endingRound;
    uint32 lastReportedRound;
    uint32 lastStartedRound;
    int256 latestSubmission;
    uint16 index;
    address admin;
    address pendingAdmin;
  }

  struct Requester {
    bool authorized;
    uint32 delay;
    uint32 lastStartedRound;
  }

  struct Funds {
    uint128 available;
    uint128 allocated;
  }

  AggregatorValidatorInterface public validator;

  // Round related params
  uint128 public paymentAmount;
  uint32 public maxSubmissionCount;
  uint32 public minSubmissionCount;
  uint32 public restartDelay;
  uint32 public timeout;
  uint8 public override decimals;
  string public override description;

  int256 immutable public minSubmissionValue;
  int256 immutable public maxSubmissionValue;

  uint256 constant public override version = 3;

  /**
   * @notice To ensure owner isn't withdrawing required funds as oracles are
   * submitting updates, we enforce that the contract maintains a minimum
   * reserve of RESERVE_ROUNDS * oracleCount() wFTN earmarked for payment to
   * oracles. (Of course, this doesn't prevent the contract from running out of
   * funds without the owner's intervention.)
   */
  uint256 constant private RESERVE_ROUNDS = 2;
  uint256 constant private MAX_ORACLE_COUNT = 77;
  uint32 constant private ROUND_MAX = type(uint32).max;
  uint256 private constant VALIDATOR_GAS_LIMIT = 100000;
  // An error specific to the Aggregator V3 Interface, to prevent possible
  // confusion around accidentally reading unset values as reported values.
  string constant private V3_NO_DATA_ERROR = "No data present";

  uint32 private reportingRoundId;
  uint32 internal latestRoundId;
  mapping(address => OracleStatus) private oracles;
  mapping(uint32 => Round) internal rounds;
  mapping(uint32 => RoundDetails) internal details;
  mapping(address => Requester) internal requesters;
  address[] private oracleAddresses;

  bytes32 public constant ADMIN_ROLE = 0xa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775;
  Funds private recordedFunds;

  event AvailableFundsUpdated(
    uint256 indexed amount
  );
  event RoundDetailsUpdated(
    uint128 indexed paymentAmount,
    uint32 indexed minSubmissionCount,
    uint32 indexed maxSubmissionCount,
    uint32 restartDelay,
    uint32 timeout // measured in seconds
  );
  event OraclePermissionsUpdated(
    address indexed oracle,
    bool indexed whitelisted
  );
  event OracleAdminUpdated(
    address indexed oracle,
    address indexed newAdmin
  );
  event OracleAdminUpdateRequested(
    address indexed oracle,
    address admin,
    address newAdmin
  );
  event SubmissionReceived(
    int256 indexed submission,
    uint32 indexed round,
    address indexed oracle
  );
  event RequesterPermissionsSet(
    address indexed requester,
    bool authorized,
    uint32 delay
  );
  event ValidatorUpdated(
    address indexed previous,
    address indexed current
  );

  /**
   * @notice set up the aggregator with initial configuration
   * @param _paymentAmount The amount paid of FTN paid to each oracle per submission, in wei (units of 10⁻¹⁸ wFTN)
   * @param _timeout is the number of seconds after the previous round that are
   * allowed to lapse before allowing an oracle to skip an unfinished round
   * _validator is an optional contract address for validating
   * external validation of answers
   * @param _minSubmissionValue is an immutable check for a lower bound of what
   * submission values are accepted from an oracle
   * @param _maxSubmissionValue is an immutable check for an upper bound of what
   * submission values are accepted from an oracle
   * @param _decimals represents the number of decimals to offset the answer by
   * @param _description a short description of what is being reported
   */
  constructor(
    uint128 _paymentAmount,
    uint32 _timeout,
    // address _validator,
    int256 _minSubmissionValue,
    int256 _maxSubmissionValue,
    uint8 _decimals,
    string memory _description
  ) {
    _setupRole(ADMIN_ROLE, msg.sender);
    _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    updateFutureRounds(_paymentAmount, 0, 0, 0, _timeout);
    // setValidator(_validator);
    minSubmissionValue = _minSubmissionValue;
    maxSubmissionValue = _maxSubmissionValue;
    decimals = _decimals;
    description = _description;
    rounds[0].updatedAt = uint64(block.timestamp - (uint256(_timeout)));
  }

  /**
   * @notice called by oracles when they have witnessed a need to update
   * @param _roundId is the ID of the round this submission pertains to
   * @param _submission is the updated data that the oracle is submitting
   */
  function submit(uint256 _roundId, int256 _submission)
    external
  {
    bytes memory error = validateOracleRound(msg.sender, uint32(_roundId));
    require(_submission >= minSubmissionValue, "value below minSubmissionValue");
    require(_submission <= maxSubmissionValue, "value above maxSubmissionValue");
    require(error.length == 0, string(error));

    oracleInitializeNewRound(uint32(_roundId));
    recordSubmission(_submission, uint32(_roundId));
    (bool updated, int256 newAnswer) = updateRoundAnswer(uint32(_roundId));
    payOracle(uint32(_roundId));
    deleteRoundDetails(uint32(_roundId));
    // TODO check this part
    // if (updated) {
    //   validateAnswer(uint32(_roundId), newAnswer);
    // }
  }
  fallback() external payable{
    updateAvailableFunds();
  }
  receive() external payable{
    updateAvailableFunds();
  }
  /**
   * @notice called by the owner to remove and add new oracles as well as
   * update the round related parameters that pertain to total oracle count
   * @param _removed is the list of addresses for the new Oracles being removed
   * @param _added is the list of addresses for the new Oracles being added
   * @param _addedAdmins is the admin addresses for the new respective _added
   * list. Only this address is allowed to access the respective oracle's funds
   * @param _minSubmissions is the new minimum submission count for each round
   * @param _maxSubmissions is the new maximum submission count for each round
   * @param _restartDelay is the number of rounds an Oracle has to wait before
   * they can initiate a round
   */
  function changeOracles(
    address[] calldata _removed,
    address[] calldata _added,
    address[] calldata _addedAdmins,
    uint32 _minSubmissions,
    uint32 _maxSubmissions,
    uint32 _restartDelay
  )
    external
    onlyRole(ADMIN_ROLE)
  {
    for (uint256 i = 0; i < _removed.length; i++) {
      removeOracle(_removed[i]);
    }

    require(_added.length == _addedAdmins.length, "need same oracle and admin count");
    require(uint256(oracleCount()) + (_added.length) <= MAX_ORACLE_COUNT, "max oracles allowed");

    for (uint256 i = 0; i < _added.length; i++) {
      addOracle(_added[i], _addedAdmins[i]);
    }

    updateFutureRounds(paymentAmount, _minSubmissions, _maxSubmissions, _restartDelay, timeout);
  }

  /**
   * @notice update the round and payment related parameters for subsequent
   * rounds
   * @param _paymentAmount is the payment amount for subsequent rounds
   * @param _minSubmissions is the new minimum submission count for each round
   * @param _maxSubmissions is the new maximum submission count for each round
   * @param _restartDelay is the number of rounds an Oracle has to wait before
   * they can initiate a round
   */
  function updateFutureRounds(
    uint128 _paymentAmount,
    uint32 _minSubmissions,
    uint32 _maxSubmissions,
    uint32 _restartDelay,
    uint32 _timeout
  )
    public
    onlyRole(ADMIN_ROLE)
  {
    uint32 oracleNum = oracleCount(); // Save on storage reads
    require(_maxSubmissions >= _minSubmissions, "max must equal/exceed min");
    require(oracleNum >= _maxSubmissions, "max cannot exceed total");
    require(oracleNum == 0 || oracleNum > _restartDelay, "delay cannot exceed total");
    require(recordedFunds.available >= requiredReserve(_paymentAmount), "insufficient funds for payment");
    if (oracleCount() > 0) {
      require(_minSubmissions > 0, "min must be greater than 0");
    }

    paymentAmount = _paymentAmount;
    minSubmissionCount = _minSubmissions;
    maxSubmissionCount = _maxSubmissions;
    restartDelay = _restartDelay;
    timeout = _timeout;

    emit RoundDetailsUpdated(
      paymentAmount,
      _minSubmissions,
      _maxSubmissions,
      _restartDelay,
      _timeout
    );
  }

  /**
   * @notice the amount of payment yet to be withdrawn by oracles
   */
  function allocatedFunds()
    external
    view
    returns (uint128)
  {
    return recordedFunds.allocated;
  }

  /**
   * @notice the amount of future funding available to oracles
   */
  function availableFunds()
    external
    view
    returns (uint128)
  {
    return recordedFunds.available;
  }

  /**
   * @notice recalculate the amount of wFTN available for payouts
   */
  function updateAvailableFunds()
    public
  {
    Funds memory funds = recordedFunds;

    uint256 nowAvailable = address(this).balance - (funds.allocated);

    if (funds.available != nowAvailable) {
      recordedFunds.available = uint128(nowAvailable);
      emit AvailableFundsUpdated(nowAvailable);
    }
  }

  /**
   * @notice returns the number of oracles
   */
  function oracleCount() public view returns (uint8) {
    return uint8(oracleAddresses.length);
  }

  /**
   * @notice returns an array of addresses containing the oracles on contract
   */
  function getOracles() external view returns (address[] memory) {
    return oracleAddresses;
  }

  /**
   * @notice get the most recently reported answer
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestAnswer()
    public
    view
    virtual
    override
    returns (int256)
  {
    return rounds[latestRoundId].answer;
  }

  /**
   * @notice get the most recent updated at timestamp
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestTimestamp()
    public
    view
    virtual
    override
    returns (uint256)
  {
    return rounds[latestRoundId].updatedAt;
  }

  /**
   * @notice get the ID of the last updated round
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestRound()
    public
    view
    virtual
    override
    returns (uint256)
  {
    return latestRoundId;
  }

  /**
   * @notice get past rounds answers
   * @param _roundId the round number to retrieve the answer for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getAnswer(uint256 _roundId)
    public
    view
    virtual
    override
    returns (int256)
  {
    if (validRoundId(_roundId)) {
      return rounds[uint32(_roundId)].answer;
    }
    return 0;
  }

  /**
   * @notice get timestamp when an answer was last updated
   * @param _roundId the round number to retrieve the updated timestamp for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getTimestamp(uint256 _roundId)
    public
    view
    virtual
    override
    returns (uint256)
  {
    if (validRoundId(_roundId)) {
      return rounds[uint32(_roundId)].updatedAt;
    }
    return 0;
  }

  /**
   * @notice get data about a round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * @param _roundId the round ID to retrieve the round data for
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answeredInRound is equal to roundId when the round didn't time out
   * and was completed regularly.
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet received
   * maxSubmissions) answer and updatedAt may change between queries.
   */
  function getRoundData(uint80 _roundId)
    public
    view
    virtual
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    Round memory r = rounds[uint32(_roundId)];

    require(r.answeredInRound > 0 && validRoundId(_roundId), V3_NO_DATA_ERROR);

    return (
      _roundId,
      r.answer,
      r.startedAt,
      r.updatedAt,
      r.answeredInRound
    );
  }

  /**
   * @notice get data about the latest round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values. Consumers are encouraged to
   * use this more fully featured method over the "legacy" latestRound/
   * latestAnswer/latestTimestamp functions. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answeredInRound is equal to roundId when the round didn't time
   * out and was completed regularly.
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet
   * received maxSubmissions) answer and updatedAt may change between queries.
   */
   function latestRoundData()
    public
    view
    virtual
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return getRoundData(latestRoundId);
  }


/**
 * @notice query the available amount of wFTN for an oracle to withdraw
 */
function withdrawablePayment(address _oracle)
  external
  view
  returns (uint256)
{
  return oracles[_oracle].withdrawable;
}
    /**
   * @notice Internal function to safely send FTN.
   * @param to Recipient address.
   * @param amount Amount of ETH to send.
   */
    function _sendViaCall(
      address payable to,
      uint256 amount
  ) internal {
      (bool sent, ) = to.call{value: amount} ("");
      if (!sent) {
          revert();
      }
  }

  /**
   * @notice transfers the oracle's wFTN to another address. Can only be called
   * by the oracle's admin.
   * @param _oracle is the oracle whose FTN is transferred
   * @param _recipient is the address to send the FTN to
   * @param _amount is the amount of FTN to send
   */
  function withdrawPayment(address _oracle, address _recipient, uint256 _amount)
    external
  {
    require(oracles[_oracle].admin == msg.sender, "only callable by admin");

    uint128 amount = uint128(_amount);
    uint128 available = oracles[_oracle].withdrawable;
    require(available >= amount, "insufficient withdrawable funds");

    oracles[_oracle].withdrawable = available - (amount);
    recordedFunds.allocated = recordedFunds.allocated - (amount);

    _sendViaCall(payable(_recipient), uint256(amount));
  }

  /**
   * @notice transfers the owner's wFTN to another address
   * @param _recipient is the address to send the wFTN to
   * @param _amount is the amount of wFTN to send
   */
  function withdrawFunds(address _recipient, uint256 _amount)
    external
    onlyRole(ADMIN_ROLE)
  {
    uint256 available = uint256(recordedFunds.available);
    require(available - (requiredReserve(paymentAmount)) >= _amount, "insufficient reserve funds");
    _sendViaCall(payable(_recipient), _amount);
    updateAvailableFunds();
  }

  /**
   * @notice get the admin address of an oracle
   * @param _oracle is the address of the oracle whose admin is being queried
   */
  function getAdmin(address _oracle)
    external
    view
    returns (address)
  {
    return oracles[_oracle].admin;
  }

  /**
   * @notice transfer the admin address for an oracle
   * @param _oracle is the address of the oracle whose admin is being transferred
   * @param _newAdmin is the new admin address
   */
  function transferAdmin(address _oracle, address _newAdmin)
    external
  {
    require(oracles[_oracle].admin == msg.sender, "only callable by admin");
    oracles[_oracle].pendingAdmin = _newAdmin;

    emit OracleAdminUpdateRequested(_oracle, msg.sender, _newAdmin);
  }

  /**
   * @notice accept the admin address transfer for an oracle
   * @param _oracle is the address of the oracle whose admin is being transferred
   */
  function acceptAdmin(address _oracle)
    external
  {
    require(oracles[_oracle].pendingAdmin == msg.sender, "only callable by pending admin");
    oracles[_oracle].pendingAdmin = address(0);
    oracles[_oracle].admin = msg.sender;

    emit OracleAdminUpdated(_oracle, msg.sender);
  }

  /**
   * @notice allows non-oracles to request a new round
   */
  function requestNewRound()
    external
    returns (uint80)
  {
    require(requesters[msg.sender].authorized, "not authorized requester");

    uint32 current = reportingRoundId;
    require(rounds[current].updatedAt > 0 || timedOut(current), "prev round must be supersedable");

    uint32 newRoundId = current + 1;
    requesterInitializeNewRound(newRoundId);
    return newRoundId;
  }

  /**
   * @notice allows the owner to specify new non-oracles to start new rounds
   * @param _requester is the address to set permissions for
   * @param _authorized is a boolean specifying whether they can start new rounds or not
   * @param _delay is the number of rounds the requester must wait before starting another round
   */
  function setRequesterPermissions(address _requester, bool _authorized, uint32 _delay)
    external
    onlyRole(ADMIN_ROLE)
  {
    if (requesters[_requester].authorized == _authorized) return;

    if (_authorized) {
      requesters[_requester].authorized = _authorized;
      requesters[_requester].delay = _delay;
    } else {
      delete requesters[_requester];
    }

    emit RequesterPermissionsSet(_requester, _authorized, _delay);
  }

  /**
   * @notice a method to provide all current info oracles need. Intended only
   * only to be callable by oracles. Not for use by contracts to read state.
   * @param _oracle the address to look up information for.
   */
  function oracleRoundState(address _oracle, uint32 _queriedRoundId)
    external
    view
    returns (
      bool _eligibleToSubmit,
      uint32 _roundId,
      int256 _latestSubmission,
      uint64 _startedAt,
      uint64 _timeout,
      uint128 _availableFunds,
      uint8 _oracleCount,
      uint128 _paymentAmount
    )
  {
    require(msg.sender == tx.origin, "off-chain reading only");

    if (_queriedRoundId > 0) {
      Round storage round = rounds[_queriedRoundId];
      RoundDetails storage details = details[_queriedRoundId];
      return (
        eligibleForSpecificRound(_oracle, _queriedRoundId),
        _queriedRoundId,
        oracles[_oracle].latestSubmission,
        round.startedAt,
        details.timeout,
        recordedFunds.available,
        oracleCount(),
        (round.startedAt > 0 ? details.paymentAmount : paymentAmount)
      );
    } else {
            return oracleRoundStateSuggestRound(_oracle);
    }
  }

  /**
   * @notice method to update the address which does external data validation.
   * @param _newValidator designates the address of the new validation contract.
   */
  function setValidator(address _newValidator)
    public
    onlyRole(ADMIN_ROLE)
  {
    address previous = address(validator);

    if (previous != _newValidator) {
      validator = AggregatorValidatorInterface(_newValidator);

      emit ValidatorUpdated(previous, _newValidator);
    }
  }


  /**
   * Private
   */

  function initializeNewRound(uint32 _roundId)
    private
  {
    updateTimedOutRoundInfo(_roundId - 1);

    reportingRoundId = _roundId;
    RoundDetails memory nextDetails = RoundDetails(
      new int256[](0),
      maxSubmissionCount,
      minSubmissionCount,
      timeout,
      paymentAmount
    );
    details[_roundId] = nextDetails;
    rounds[_roundId].startedAt = uint64(block.timestamp);

    emit NewRound(_roundId, msg.sender, rounds[_roundId].startedAt);
  }

  function oracleInitializeNewRound(uint32 _roundId)
    private
  {
    if (!newRound(_roundId)) return;
    uint256 lastStarted = oracles[msg.sender].lastStartedRound; // cache storage reads
    if (_roundId <= lastStarted + restartDelay && lastStarted != 0) return;

    initializeNewRound(_roundId);

    oracles[msg.sender].lastStartedRound = _roundId;
  }

  function requesterInitializeNewRound(uint32 _roundId)
    private
  {
    if (!newRound(_roundId)) return;
    uint256 lastStarted = requesters[msg.sender].lastStartedRound; // cache storage reads
    require(_roundId > lastStarted + requesters[msg.sender].delay || lastStarted == 0, "must delay requests");

    initializeNewRound(_roundId);

    requesters[msg.sender].lastStartedRound = _roundId;
  }

  function updateTimedOutRoundInfo(uint32 _roundId)
    private
  {
    if (!timedOut(_roundId)) return;

    uint32 prevId = _roundId - 1;
    rounds[_roundId].answer = rounds[prevId].answer;
    rounds[_roundId].answeredInRound = rounds[prevId].answeredInRound;
    rounds[_roundId].updatedAt = uint64(block.timestamp);

    delete details[_roundId];
  }

  function eligibleForSpecificRound(address _oracle, uint32 _queriedRoundId)
    private
    view
    returns (bool _eligible)
  {
    if (rounds[_queriedRoundId].startedAt > 0) {
      return acceptingSubmissions(_queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
    } else {
      return delayed(_oracle, _queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
    }
  }

  function oracleRoundStateSuggestRound(address _oracle)
    private
    view
    returns (
      bool _eligibleToSubmit,
      uint32 _roundId,
      int256 _latestSubmission,
      uint64 _startedAt,
      uint64 _timeout,
      uint128 _availableFunds,
      uint8 _oracleCount,
      uint128 _paymentAmount
    )
  {
    Round storage round = rounds[0];
    OracleStatus storage oracle = oracles[_oracle];

    bool shouldSupersede = oracle.lastReportedRound == reportingRoundId || !acceptingSubmissions(reportingRoundId);
    // Instead of nudging oracles to submit to the next round, the inclusion of
    // the shouldSupersede bool in the if condition pushes them towards
    // submitting in a currently open round.
    if (supersedable(reportingRoundId) && shouldSupersede) {
      _roundId = reportingRoundId + 1;
      round = rounds[_roundId];

      _paymentAmount = paymentAmount;
      _eligibleToSubmit = delayed(_oracle, _roundId);
    } else {
      _roundId = reportingRoundId;
      round = rounds[_roundId];

      _paymentAmount = details[_roundId].paymentAmount;
      _eligibleToSubmit = acceptingSubmissions(_roundId);
    }
    
    if (validateOracleRound(_oracle, _roundId).length != 0) {
      _eligibleToSubmit = false;
    }

    return (
      _eligibleToSubmit,
      _roundId,
      oracle.latestSubmission,
      round.startedAt,
      details[_roundId].timeout,
      recordedFunds.available,
      oracleCount(),
      _paymentAmount
    );
  }

  function updateRoundAnswer(uint32 _roundId)
    internal
    returns (bool, int256)
  {
    if (details[_roundId].submissions.length < details[_roundId].minSubmissions) {
      return (false, 0);
    }

    int256 newAnswer = Median.calculateInplace(details[_roundId].submissions);
    rounds[_roundId].answer = newAnswer;
    rounds[_roundId].updatedAt = uint64(block.timestamp);
    rounds[_roundId].answeredInRound = _roundId;
    latestRoundId = _roundId;

    emit AnswerUpdated(newAnswer, _roundId, block.timestamp);

    return (true, newAnswer);
  }

  function validateAnswer(
    uint32 _roundId,
    int256 _newAnswer
  )
    private
  {
    AggregatorValidatorInterface av = validator; // cache storage reads
    if (address(av) == address(0)) return;

    uint32 prevRound = _roundId - 1;
    uint32 prevAnswerRoundId = rounds[prevRound].answeredInRound;
    int256 prevRoundAnswer = rounds[prevRound].answer;
    // We do not want the validator to ever prevent reporting, so we limit its
    // gas usage and catch any errors that may arise.
    try av.validate{gas: VALIDATOR_GAS_LIMIT}(
      prevAnswerRoundId,
      prevRoundAnswer,
      _roundId,
      _newAnswer
    ) {} catch {}
  }

  function payOracle(uint32 _roundId)
    private
  {
    uint128 payment = details[_roundId].paymentAmount;
    Funds memory funds = recordedFunds;
    funds.available = funds.available - payment;
    funds.allocated = funds.allocated + payment;
    recordedFunds = funds;
    oracles[msg.sender].withdrawable = oracles[msg.sender].withdrawable + payment;

    emit AvailableFundsUpdated(funds.available);
  }

  function recordSubmission(int256 _submission, uint32 _roundId)
    private
  {
    require(acceptingSubmissions(_roundId), "round not accepting submissions");

    details[_roundId].submissions.push(_submission);
    oracles[msg.sender].lastReportedRound = _roundId;
    oracles[msg.sender].latestSubmission = _submission;

    emit SubmissionReceived(_submission, _roundId, msg.sender);
  }

  function deleteRoundDetails(uint32 _roundId)
    private
  {
    if (details[_roundId].submissions.length < details[_roundId].maxSubmissions) return;

    delete details[_roundId];
  }

  function timedOut(uint32 _roundId)
    private
    view
    returns (bool)
  {
    uint64 startedAt = rounds[_roundId].startedAt;
    uint32 roundTimeout = details[_roundId].timeout;
    return startedAt > 0 && roundTimeout > 0 && startedAt + roundTimeout < block.timestamp;
  }

  function getStartingRound(address _oracle)
    private
    view
    returns (uint32)
  {
    uint32 currentRound = reportingRoundId;
    if (currentRound != 0 && currentRound == oracles[_oracle].endingRound) {
      return currentRound;
    }
    return currentRound + 1;
  }

  function previousAndCurrentUnanswered(uint32 _roundId, uint32 _rrId)
    private
    view
    returns (bool)
  {
    return _roundId + 1 == _rrId && rounds[_rrId].updatedAt == 0;
  }

  function requiredReserve(uint256 payment)
    private
    view
    returns (uint256)
  {
    return payment * oracleCount() * RESERVE_ROUNDS;
  }

  function addOracle(
    address _oracle,
    address _admin
  )
    private
  {
    require(!oracleEnabled(_oracle), "oracle already enabled");

    require(_admin != address(0), "cannot set admin to 0");
    require(oracles[_oracle].admin == address(0) || oracles[_oracle].admin == _admin, "owner cannot overwrite admin");

    oracles[_oracle].startingRound = getStartingRound(_oracle);
    oracles[_oracle].endingRound = ROUND_MAX;
    oracles[_oracle].index = uint16(oracleAddresses.length);
    oracleAddresses.push(_oracle);
    oracles[_oracle].admin = _admin;

    emit OraclePermissionsUpdated(_oracle, true);
    emit OracleAdminUpdated(_oracle, _admin);
  }

  function removeOracle(
    address _oracle
  )
    private
  {
    require(oracleEnabled(_oracle), "oracle not enabled");

    oracles[_oracle].endingRound = reportingRoundId + 1;
    address tail = oracleAddresses[uint256(oracleCount()) - 1];
    uint16 index = oracles[_oracle].index;
    oracles[tail].index = index;
    delete oracles[_oracle].index;
    oracleAddresses[index] = tail;
    oracleAddresses.pop();

    emit OraclePermissionsUpdated(_oracle, false);
  }

  function validateOracleRound(address _oracle, uint32 _roundId)
    private
    view
    returns (bytes memory)
  {
    // cache storage reads
    uint32 startingRound = oracles[_oracle].startingRound;
    uint32 rrId = reportingRoundId;

    if (startingRound == 0) return "not enabled oracle";
    if (startingRound > _roundId) return "not yet enabled oracle";
    if (oracles[_oracle].endingRound < _roundId) return "no longer allowed oracle";
    if (oracles[_oracle].lastReportedRound >= _roundId) return "cannot report on previous rounds";
    if (_roundId != rrId && _roundId != rrId + 1 && !previousAndCurrentUnanswered(_roundId, rrId)) return "invalid round to report";
    if (_roundId != 1 && !supersedable(_roundId - 1)) return "previous round not supersedable";
  }

  function supersedable(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return rounds[_roundId].updatedAt > 0 || timedOut(_roundId);
  }

  function oracleEnabled(address _oracle)
    private
    view
    returns (bool)
  {
    return oracles[_oracle].endingRound == ROUND_MAX;
  }

  function acceptingSubmissions(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return details[_roundId].maxSubmissions != 0;
  }

  function delayed(address _oracle, uint32 _roundId)
    private
    view
    returns (bool)
  {
    uint256 lastStarted = oracles[_oracle].lastStartedRound;
    return _roundId > lastStarted + restartDelay || lastStarted == 0;
  }

  function newRound(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return _roundId == reportingRoundId + 1;
  }

  function validRoundId(uint256 _roundId)
    private
    pure
    returns (bool)
  {
    return _roundId <= ROUND_MAX;
  }

}
        

contracts/interfaces/AggregatorValidatorInterface.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

interface AggregatorValidatorInterface {
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  ) external returns (bool);
}
          

@openzeppelin/contracts/access/AccessControl.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}
          

@openzeppelin/contracts/access/IAccessControl.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}
          

@openzeppelin/contracts/utils/Context.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
          

@openzeppelin/contracts/utils/Strings.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}
          

@openzeppelin/contracts/utils/introspection/ERC165.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
          

@openzeppelin/contracts/utils/introspection/IERC165.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
          

@openzeppelin/contracts/utils/math/Math.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}
          

@openzeppelin/contracts/utils/math/SignedMath.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}
          

contracts/Median.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

// import "./vendor/SafeMathChainlink.sol";
import "./SignedSafeMath.sol";

library Median {
  using SignedSafeMath for int256;

  int256 constant INT_MAX = type(int256).max;

  /**
   * @notice Returns the sorted middle, or the average of the two middle indexed items if the
   * array has an even number of elements.
   * @dev The list passed as an argument isn't modified.
   * @dev This algorithm has expected runtime O(n), but for adversarially chosen inputs
   * the runtime is O(n^2).
   * @param list The list of elements to compare
   */
  function calculate(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    return calculateInplace(copy(list));
  }

  /**
   * @notice See documentation for function calculate.
   * @dev The list passed as an argument may be permuted.
   */
  function calculateInplace(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    require(0 < list.length, "list must not be empty");
    uint256 len = list.length;
    uint256 middleIndex = len / 2;
    if (len % 2 == 0) {
      int256 median1;
      int256 median2;
      (median1, median2) = quickselectTwo(list, 0, len - 1, middleIndex - 1, middleIndex);
      return SignedSafeMath.avg(median1, median2);
    } else {
      return quickselect(list, 0, len - 1, middleIndex);
    }
  }

  /**
   * @notice Maximum length of list that shortSelectTwo can handle
   */
  uint256 constant SHORTSELECTTWO_MAX_LENGTH = 7;

  /**
   * @notice Select the k1-th and k2-th element from list of length at most 7
   * @dev Uses an optimal sorting network
   */
  function shortSelectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    private
    pure
    returns (int256 k1th, int256 k2th)
  {
    // Uses an optimal sorting network (https://en.wikipedia.org/wiki/Sorting_network)
    // for lists of length 7. Network layout is taken from
    // http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=7&algorithm=hibbard&output=svg

    uint256 len = hi + 1 - lo;
    int256 x0 = list[lo + 0];
    int256 x1 = 1 < len ? list[lo + 1] : INT_MAX;
    int256 x2 = 2 < len ? list[lo + 2] : INT_MAX;
    int256 x3 = 3 < len ? list[lo + 3] : INT_MAX;
    int256 x4 = 4 < len ? list[lo + 4] : INT_MAX;
    int256 x5 = 5 < len ? list[lo + 5] : INT_MAX;
    int256 x6 = 6 < len ? list[lo + 6] : INT_MAX;

    if (x0 > x1) {(x0, x1) = (x1, x0);}
    if (x2 > x3) {(x2, x3) = (x3, x2);}
    if (x4 > x5) {(x4, x5) = (x5, x4);}
    if (x0 > x2) {(x0, x2) = (x2, x0);}
    if (x1 > x3) {(x1, x3) = (x3, x1);}
    if (x4 > x6) {(x4, x6) = (x6, x4);}
    if (x1 > x2) {(x1, x2) = (x2, x1);}
    if (x5 > x6) {(x5, x6) = (x6, x5);}
    if (x0 > x4) {(x0, x4) = (x4, x0);}
    if (x1 > x5) {(x1, x5) = (x5, x1);}
    if (x2 > x6) {(x2, x6) = (x6, x2);}
    if (x1 > x4) {(x1, x4) = (x4, x1);}
    if (x3 > x6) {(x3, x6) = (x6, x3);}
    if (x2 > x4) {(x2, x4) = (x4, x2);}
    if (x3 > x5) {(x3, x5) = (x5, x3);}
    if (x3 > x4) {(x3, x4) = (x4, x3);}

    uint256 index1 = k1 - lo;
    if (index1 == 0) {k1th = x0;}
    else if (index1 == 1) {k1th = x1;}
    else if (index1 == 2) {k1th = x2;}
    else if (index1 == 3) {k1th = x3;}
    else if (index1 == 4) {k1th = x4;}
    else if (index1 == 5) {k1th = x5;}
    else if (index1 == 6) {k1th = x6;}
    else {revert("k1 out of bounds");}

    uint256 index2 = k2 - lo;
    if (k1 == k2) {return (k1th, k1th);}
    else if (index2 == 0) {return (k1th, x0);}
    else if (index2 == 1) {return (k1th, x1);}
    else if (index2 == 2) {return (k1th, x2);}
    else if (index2 == 3) {return (k1th, x3);}
    else if (index2 == 4) {return (k1th, x4);}
    else if (index2 == 5) {return (k1th, x5);}
    else if (index2 == 6) {return (k1th, x6);}
    else {revert("k2 out of bounds");}
  }

  /**
   * @notice Selects the k-th ranked element from list, looking only at indices between lo and hi
   * (inclusive). Modifies list in-place.
   */
  function quickselect(int256[] memory list, uint256 lo, uint256 hi, uint256 k)
    private
    pure
    returns (int256 kth)
  {
    require(lo <= k);
    require(k <= hi);
    while (lo < hi) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        int256 ignore;
        (kth, ignore) = shortSelectTwo(list, lo, hi, k, k);
        return kth;
      }
      uint256 pivotIndex = partition(list, lo, hi);
      if (k <= pivotIndex) {
        // since pivotIndex < (original hi passed to partition),
        // termination is guaranteed in this case
        hi = pivotIndex;
      } else {
        // since (original lo passed to partition) <= pivotIndex,
        // termination is guaranteed in this case
        lo = pivotIndex + 1;
      }
    }
    return list[lo];
  }

  /**
   * @notice Selects the k1-th and k2-th ranked elements from list, looking only at indices between
   * lo and hi (inclusive). Modifies list in-place.
   */
  function quickselectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    internal // for testing
    pure
    returns (int256 k1th, int256 k2th)
  {
    require(k1 < k2);
    require(lo <= k1 && k1 <= hi);
    require(lo <= k2 && k2 <= hi);

    while (true) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        return shortSelectTwo(list, lo, hi, k1, k2);
      }
      uint256 pivotIdx = partition(list, lo, hi);
      if (k2 <= pivotIdx) {
        hi = pivotIdx;
      } else if (pivotIdx < k1) {
        lo = pivotIdx + 1;
      } else {
        assert(k1 <= pivotIdx && pivotIdx < k2);
        k1th = quickselect(list, lo, pivotIdx, k1);
        k2th = quickselect(list, pivotIdx + 1, hi, k2);
        return (k1th, k2th);
      }
    }
  }

  /**
   * @notice Partitions list in-place using Hoare's partitioning scheme.
   * Only elements of list between indices lo and hi (inclusive) will be modified.
   * Returns an index i, such that:
   * - lo <= i < hi
   * - forall j in [lo, i]. list[j] <= list[i]
   * - forall j in [i, hi]. list[i] <= list[j]
   */
  function partition(int256[] memory list, uint256 lo, uint256 hi)
    private
    pure
    returns (uint256)
  {
    // We don't care about overflow of the addition, because it would require a list
    // larger than any feasible computer's memory.
    int256 pivot = list[(lo + hi) / 2];
    lo -= 1; // this can underflow. that's intentional.
    hi += 1;
    while (true) {
      do {
        lo += 1;
      } while (list[lo] < pivot);
      do {
        hi -= 1;
      } while (list[hi] > pivot);
      if (lo < hi) {
        (list[lo], list[hi]) = (list[hi], list[lo]);
      } else {
        // Let orig_lo and orig_hi be the original values of lo and hi passed to partition.
        // Then, hi < orig_hi, because hi decreases *strictly* monotonically
        // in each loop iteration and
        // - either list[orig_hi] > pivot, in which case the first loop iteration
        //   will achieve hi < orig_hi;
        // - or list[orig_hi] <= pivot, in which case at least two loop iterations are
        //   needed:
        //   - lo will have to stop at least once in the interval
        //     [orig_lo, (orig_lo + orig_hi)/2]
        //   - (orig_lo + orig_hi)/2 < orig_hi
        return hi;
      }
    }
  }

  /**
   * @notice Makes an in-memory copy of the array passed in
   * @param list Reference to the array to be copied
   */
  function copy(int256[] memory list)
    private
    pure
    returns(int256[] memory)
  {
    int256[] memory list2 = new int256[](list.length);
    for (uint256 i = 0; i < list.length; i++) {
      list2[i] = list[i];
    }
    return list2;
  }
}
          

contracts/SignedSafeMath.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

library SignedSafeMath {
    int256 private constant MIN_INT256 = type(int256).min;
    int256 private constant MAX_INT256 = type(int256).max;

    /**
     * @dev Multiplies two signed integers, reverts on overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        require(!(a == -1 && b == MIN_INT256), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == MIN_INT256), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Subtracts two signed integers, reverts on overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        require((b >= 0 && a >= b) || (b < 0 && a > b), "SignedSafeMath: subtraction overflow");

        int256 c = a - b;

        return c;
    }

    /**
     * @dev Adds two signed integers, reverts on overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        require((b >= 0 && a <= MAX_INT256 - b) || (b < 0 && a >= MIN_INT256 - b), "SignedSafeMath: addition overflow");

        int256 c = a + b;

        return c;
    }

    /**
     * @notice Computes average of two signed integers, ensuring that the computation
     * doesn't overflow.
     * @dev If the result is not an integer, it is rounded towards zero. For example,
     * avg(-3, -4) = -3
     */
    function avg(int256 _a, int256 _b) internal pure returns (int256) {
        if ((_a < 0 && _b > 0) || (_a > 0 && _b < 0)) {
            return add(_a, _b) / 2;
        }
        int256 remainder = (_a % 2 + _b % 2) / 2;
        return add(add(_a / 2, _b / 2), remainder);
    }
}
          

contracts/interfaces/AggregatorInterface.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

interface AggregatorInterface {
  function latestAnswer()
    external
    view
    returns (
      int256
    );
  
  function latestTimestamp()
    external
    view
    returns (
      uint256
    );

  function latestRound()
    external
    view
    returns (
      uint256
    );

  function getAnswer(
    uint256 roundId
  )
    external
    view
    returns (
      int256
    );

  function getTimestamp(
    uint256 roundId
  )
    external
    view
    returns (
      uint256
    );

  event AnswerUpdated(
    int256 indexed current,
    uint256 indexed roundId,
    uint256 updatedAt
  );

  event NewRound(
    uint256 indexed roundId,
    address indexed startedBy,
    uint256 startedAt
  );
}
          

contracts/interfaces/AggregatorV2V3Interface.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "./AggregatorInterface.sol";
import "./AggregatorV3Interface.sol";

interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}
          

contracts/interfaces/AggregatorV3Interface.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

interface AggregatorV3Interface {

  function decimals()
    external
    view
    returns (
      uint8
    );

  function description()
    external
    view
    returns (
      string memory
    );

  function version()
    external
    view
    returns (
      uint256
    );

  function getRoundData(
    uint80 _roundId
  )
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}
          

Compiler Settings

{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint128","name":"_paymentAmount","internalType":"uint128"},{"type":"uint32","name":"_timeout","internalType":"uint32"},{"type":"int256","name":"_minSubmissionValue","internalType":"int256"},{"type":"int256","name":"_maxSubmissionValue","internalType":"int256"},{"type":"uint8","name":"_decimals","internalType":"uint8"},{"type":"string","name":"_description","internalType":"string"}]},{"type":"event","name":"AnswerUpdated","inputs":[{"type":"int256","name":"current","internalType":"int256","indexed":true},{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"uint256","name":"updatedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AvailableFundsUpdated","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"NewRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"address","name":"startedBy","internalType":"address","indexed":true},{"type":"uint256","name":"startedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OracleAdminUpdateRequested","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"address","name":"admin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OracleAdminUpdated","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"address","name":"newAdmin","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OraclePermissionsUpdated","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"bool","name":"whitelisted","internalType":"bool","indexed":true}],"anonymous":false},{"type":"event","name":"RequesterPermissionsSet","inputs":[{"type":"address","name":"requester","internalType":"address","indexed":true},{"type":"bool","name":"authorized","internalType":"bool","indexed":false},{"type":"uint32","name":"delay","internalType":"uint32","indexed":false}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoundDetailsUpdated","inputs":[{"type":"uint128","name":"paymentAmount","internalType":"uint128","indexed":true},{"type":"uint32","name":"minSubmissionCount","internalType":"uint32","indexed":true},{"type":"uint32","name":"maxSubmissionCount","internalType":"uint32","indexed":true},{"type":"uint32","name":"restartDelay","internalType":"uint32","indexed":false},{"type":"uint32","name":"timeout","internalType":"uint32","indexed":false}],"anonymous":false},{"type":"event","name":"SubmissionReceived","inputs":[{"type":"int256","name":"submission","internalType":"int256","indexed":true},{"type":"uint32","name":"round","internalType":"uint32","indexed":true},{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ValidatorUpdated","inputs":[{"type":"address","name":"previous","internalType":"address","indexed":true},{"type":"address","name":"current","internalType":"address","indexed":true}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptAdmin","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"allocatedFunds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"availableFunds","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeOracles","inputs":[{"type":"address[]","name":"_removed","internalType":"address[]"},{"type":"address[]","name":"_added","internalType":"address[]"},{"type":"address[]","name":"_addedAdmins","internalType":"address[]"},{"type":"uint32","name":"_minSubmissions","internalType":"uint32"},{"type":"uint32","name":"_maxSubmissions","internalType":"uint32"},{"type":"uint32","name":"_restartDelay","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"description","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getAdmin","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"getAnswer","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOracles","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint80","name":"roundId","internalType":"uint80"},{"type":"int256","name":"answer","internalType":"int256"},{"type":"uint256","name":"startedAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"},{"type":"uint80","name":"answeredInRound","internalType":"uint80"}],"name":"getRoundData","inputs":[{"type":"uint80","name":"_roundId","internalType":"uint80"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTimestamp","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"latestAnswer","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestRound","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint80","name":"roundId","internalType":"uint80"},{"type":"int256","name":"answer","internalType":"int256"},{"type":"uint256","name":"startedAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"},{"type":"uint80","name":"answeredInRound","internalType":"uint80"}],"name":"latestRoundData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"maxSubmissionCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"maxSubmissionValue","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"minSubmissionCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"minSubmissionValue","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"oracleCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_eligibleToSubmit","internalType":"bool"},{"type":"uint32","name":"_roundId","internalType":"uint32"},{"type":"int256","name":"_latestSubmission","internalType":"int256"},{"type":"uint64","name":"_startedAt","internalType":"uint64"},{"type":"uint64","name":"_timeout","internalType":"uint64"},{"type":"uint128","name":"_availableFunds","internalType":"uint128"},{"type":"uint8","name":"_oracleCount","internalType":"uint8"},{"type":"uint128","name":"_paymentAmount","internalType":"uint128"}],"name":"oracleRoundState","inputs":[{"type":"address","name":"_oracle","internalType":"address"},{"type":"uint32","name":"_queriedRoundId","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"paymentAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint80","name":"","internalType":"uint80"}],"name":"requestNewRound","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"restartDelay","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRequesterPermissions","inputs":[{"type":"address","name":"_requester","internalType":"address"},{"type":"bool","name":"_authorized","internalType":"bool"},{"type":"uint32","name":"_delay","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setValidator","inputs":[{"type":"address","name":"_newValidator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submit","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"},{"type":"int256","name":"_submission","internalType":"int256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferAdmin","inputs":[{"type":"address","name":"_oracle","internalType":"address"},{"type":"address","name":"_newAdmin","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAvailableFunds","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFutureRounds","inputs":[{"type":"uint128","name":"_paymentAmount","internalType":"uint128"},{"type":"uint32","name":"_minSubmissions","internalType":"uint32"},{"type":"uint32","name":"_maxSubmissions","internalType":"uint32"},{"type":"uint32","name":"_restartDelay","internalType":"uint32"},{"type":"uint32","name":"_timeout","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract AggregatorValidatorInterface"}],"name":"validator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"version","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFunds","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawPayment","inputs":[{"type":"address","name":"_oracle","internalType":"address"},{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawablePayment","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60c06040523480156200001157600080fd5b5060405162004f8138038062004f818339810160408190526200003491620008fe565b6200004f60008051602062004f618339815191523362000112565b6200005c60003362000112565b6200006c86600080808962000122565b608084905260a08390526003805460ff191660ff841617905580516200009a906004906020840190620007c7565b50620000ad63ffffffff86164262000a95565b6000805260076020527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e080546001600160401b03929092166801000000000000000002600160401b600160801b03199092169190911790555062000b7b945050505050565b6200011e828262000486565b5050565b60008051602062004f618339815191526200013d8162000526565b600062000149600a5490565b60ff1690508563ffffffff168563ffffffff161015620001b05760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064015b60405180910390fd5b8463ffffffff168163ffffffff1610156200020e5760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401620001a7565b63ffffffff811615806200022d57508363ffffffff168163ffffffff16115b6200027b5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401620001a7565b6200028f6001600160801b03881662000535565b600b546001600160801b03161015620002eb5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401620001a7565b6000620002f7600a5490565b60ff161115620003595760008663ffffffff1611620003595760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401620001a7565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f87876040516200047592919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200011e576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620004e23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b62000532813362000564565b50565b6000600262000543600a5490565b620005529060ff168462000a73565b6200055e919062000a73565b92915050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200011e57620005a381620005f460201b62001c0f1760201c565b620005b983602062001c2162000607821b17811c565b604051602001620005cc929190620009aa565b60408051601f198184030181529082905262461bcd60e51b8252620001a79160040162000a23565b60606200055e6001600160a01b03831660145b606060006200061883600262000a73565b6200062590600262000a58565b6001600160401b038111156200063f576200063f62000b65565b6040519080825280601f01601f1916602001820160405280156200066a576020820181803683370190505b509050600360fc1b8160008151811062000688576200068862000b4f565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620006ba57620006ba62000b4f565b60200101906001600160f81b031916908160001a9053506000620006e084600262000a73565b620006ed90600162000a58565b90505b60018111156200076f576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811062000725576200072562000b4f565b1a60f81b8282815181106200073e576200073e62000b4f565b60200101906001600160f81b031916908160001a90535060049490941c93620007678162000ae2565b9050620006f0565b508315620007c05760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620001a7565b9392505050565b828054620007d59062000afc565b90600052602060002090601f016020900481019282620007f9576000855562000844565b82601f106200081457805160ff191683800117855562000844565b8280016001018555821562000844579182015b828111156200084457825182559160200191906001019062000827565b506200085292915062000856565b5090565b5b8082111562000852576000815560010162000857565b600082601f8301126200087f57600080fd5b81516001600160401b03808211156200089c576200089c62000b65565b604051601f8301601f19908116603f01168101908282118183101715620008c757620008c762000b65565b81604052838152866020858801011115620008e157600080fd5b620008f484602083016020890162000aaf565b9695505050505050565b60008060008060008060c087890312156200091857600080fd5b86516001600160801b03811681146200093057600080fd5b602088015190965063ffffffff811681146200094b57600080fd5b809550506040870151935060608701519250608087015160ff811681146200097257600080fd5b60a08801519092506001600160401b038111156200098f57600080fd5b6200099d89828a016200086d565b9150509295509295509295565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351620009e481601785016020880162000aaf565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835162000a1781602884016020880162000aaf565b01602801949350505050565b602081526000825180602084015262000a4481604085016020870162000aaf565b601f01601f19169190910160400192915050565b6000821982111562000a6e5762000a6e62000b39565b500190565b600081600019048311821515161562000a905762000a9062000b39565b500290565b60008282101562000aaa5762000aaa62000b39565b500390565b60005b8381101562000acc57818101518382015260200162000ab2565b8381111562000adc576000848401525b50505050565b60008162000af45762000af462000b39565b506000190190565b600181811c9082168062000b1157607f821691505b6020821081141562000b3357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160a0516143b262000baf600039600081816103290152610b7f0152600081816106ae0152610b0a01526143b26000f3fe60806040526004361061026b5760003560e01c806364efb22b11610144578063a217fddf116100b6578063c93745001161007a578063c9374500146108ce578063d4cc54e4146108f2578063d547741f14610917578063e2e4031714610937578063e9ee6eeb14610976578063feaf968c146109965761027a565b8063a217fddf14610839578063b5ab58dc1461084e578063b633620c1461086e578063c10753291461088e578063c35905c6146108ae5761027a565b80637c2b0b21116101085780637c2b0b211461069c5780638205bf6a146106d057806388aa80e71461071557806391d148541461079257806398e5b12a146107b25780639a6fc8f5146107e25761027a565b806364efb22b146105cf578063668a0f021461061157806370dea79a146106345780637284e4161461065857806375b238fc1461067a5761027a565b80633969c20f116101dd5780634f8fc3b5116101a15780634f8fc3b51461051a57806350d25bcd1461052f57806354fd4d501461056157806358609e4414610576578063613d8fcc1461059a578063628806ef146105af5761027a565b80633969c20f1461044e5780633a5381b51461046e5780633d3d7714146104a657806340884c52146104c657806346fcff4c146104e85761027a565b8063248a9ca31161022f578063248a9ca3146103595780632f2ff15d14610389578063313ce567146103a9578063357ebb02146103d557806336568abe1461040e57806338aa4c721461042e5761027a565b806301ffc9a7146102825780631327d3d8146102b7578063202ee0ed146102d757806320ed0275146102f757806323ca2903146103175761027a565b3661027a576102786109ab565b005b6102786109ab565b34801561028e57600080fd5b506102a261029d366004613e76565b610a41565b60405190151581526020015b60405180910390f35b3480156102c357600080fd5b506102786102d2366004613c48565b610a78565b3480156102e357600080fd5b506102786102f2366004613f13565b610afa565b34801561030357600080fd5b50610278610312366004613cd2565b610c4c565b34801561032357600080fd5b5061034b7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102ae565b34801561036557600080fd5b5061034b610374366004613e3a565b60009081526020819052604090206001015490565b34801561039557600080fd5b506102786103a4366004613e53565b610d52565b3480156103b557600080fd5b506003546103c39060ff1681565b60405160ff90911681526020016102ae565b3480156103e157600080fd5b506002546103f990600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102ae565b34801561041a57600080fd5b50610278610429366004613e53565b610d77565b34801561043a57600080fd5b50610278610449366004613ea0565b610df1565b34801561045a57600080fd5b50610278610469366004613d70565b61113d565b34801561047a57600080fd5b5060015461048e906001600160a01b031681565b6040516001600160a01b0390911681526020016102ae565b3480156104b257600080fd5b506102786104c1366004613c96565b6112f8565b3480156104d257600080fd5b506104db611455565b6040516102ae9190613fd6565b3480156104f457600080fd5b50600b546001600160801b03165b6040516001600160801b0390911681526020016102ae565b34801561052657600080fd5b506102786109ab565b34801561053b57600080fd5b50600554640100000000900463ffffffff1660009081526007602052604090205461034b565b34801561056d57600080fd5b5061034b600381565b34801561058257600080fd5b506002546103f990600160801b900463ffffffff1681565b3480156105a657600080fd5b50600a546103c3565b3480156105bb57600080fd5b506102786105ca366004613c48565b6114b7565b3480156105db57600080fd5b5061048e6105ea366004613c48565b6001600160a01b039081166000908152600660205260409020600201546201000090041690565b34801561061d57600080fd5b50600554640100000000900463ffffffff1661034b565b34801561064057600080fd5b506002546103f990600160e01b900463ffffffff1681565b34801561066457600080fd5b5061066d611598565b6040516102ae9190614023565b34801561068657600080fd5b5061034b60008051602061435d83398151915281565b3480156106a857600080fd5b5061034b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106dc57600080fd5b50600554640100000000900463ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031661034b565b34801561072157600080fd5b50610735610730366004613d46565b611626565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102ae565b34801561079e57600080fd5b506102a26107ad366004613e53565b611783565b3480156107be57600080fd5b506107c76117ac565b60405169ffffffffffffffffffff90911681526020016102ae565b3480156107ee57600080fd5b506108026107fd366004613f35565b6118b7565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102ae565b34801561084557600080fd5b5061034b600081565b34801561085a57600080fd5b5061034b610869366004613e3a565b6119bd565b34801561087a57600080fd5b5061034b610889366004613e3a565b6119f3565b34801561089a57600080fd5b506102786108a9366004613d1c565b611a34565b3480156108ba57600080fd5b50600254610502906001600160801b031681565b3480156108da57600080fd5b506002546103f990600160a01b900463ffffffff1681565b3480156108fe57600080fd5b50600b54600160801b90046001600160801b0316610502565b34801561092357600080fd5b50610278610932366004613e53565b611ad4565b34801561094357600080fd5b5061034b610952366004613c48565b6001600160a01b03166000908152600660205260409020546001600160801b031690565b34801561098257600080fd5b50610278610991366004613c63565b611af9565b3480156109a257600080fd5b50610802611bd5565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000906109e290476141e3565b82519091506001600160801b03168114610a3d57600b80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b60006001600160e01b03198216637965db0b60e01b1480610a7257506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008051602061435d833981519152610a9081611dc3565b6001546001600160a01b039081169083168114610af557600180546001600160a01b0319166001600160a01b0385811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b505050565b6000610b063384611dd0565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610b7d5760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000821315610bed5760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610b74565b8051819015610c0f5760405162461bcd60e51b8152600401610b749190614023565b50610c198361205e565b610c2382846120fc565b600080610c2f856121e2565b91509150610c3c85612340565b610c4585612456565b5050505050565b60008051602061435d833981519152610c6481611dc3565b6001600160a01b03841660009081526009602052604090205460ff1615158315151415610c9057610d4c565b8215610cd7576001600160a01b0384166000908152600960205260409020805464ffffffffff191684151564ffffffff0019161761010063ffffffff851602179055610d00565b6001600160a01b0384166000908152600960205260409020805468ffffffffffffffffff191690555b60408051841515815263ffffffff841660208201526001600160a01b038616917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b50505050565b600082815260208190526040902060010154610d6d81611dc3565b610af583836124b3565b6001600160a01b0381163314610de75760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610b74565b610a3d8282612537565b60008051602061435d833981519152610e0981611dc3565b6000610e14600a5490565b60ff1690508563ffffffff168563ffffffff161015610e755760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610b74565b8463ffffffff168163ffffffff161015610ed15760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610b74565b63ffffffff81161580610eef57508363ffffffff168163ffffffff16115b610f3b5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610b74565b610f4d876001600160801b031661259c565b600b546001600160801b03161015610fa75760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610b74565b6000610fb2600a5490565b60ff1611156110115760008663ffffffff16116110115760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610b74565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f878760405161112c92919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b60008051602061435d83398151915261115581611dc3565b60005b898110156111a15761118f8b8b8381811061117557611175614330565b905060200201602081019061118a9190613c48565b6125c0565b8061119981614295565b915050611158565b508685146111f15760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610b74565b604d876111fd600a5490565b60ff1661120a91906140c2565b111561124e5760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610b74565b60005b878110156112c1576112af89898381811061126e5761126e614330565b90506020020160208101906112839190613c48565b88888481811061129557611295614330565b90506020020160208101906112aa9190613c48565b612792565b806112b981614295565b915050611251565b506002546112ec906001600160801b03811690869086908690600160e01b900463ffffffff16610df1565b50505050505050505050565b6001600160a01b038381166000908152600660205260409020600201546201000090041633146113635760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610b74565b6001600160a01b03831660009081526006602052604090205481906001600160801b039081169082168110156113db5760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610b74565b6113e582826141bb565b6001600160a01b038616600090815260066020526040902080546001600160801b0319166001600160801b03928316179055600b5461142d918491600160801b9004166141bb565b600b80546001600160801b03928316600160801b02908316179055610c459085908416612a17565b6060600a8054806020026020016040519081016040528092919081815260200182805480156114ad57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161148f575b5050505050905090565b6001600160a01b038181166000908152600660205260409020600301541633146115235760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610b74565b6001600160a01b0381166000818152600660205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b600480546115a59061425a565b80601f01602080910402602001604051908101604052809291908181526020018280546115d19061425a565b801561161e5780601f106115f35761010080835404028352916020019161161e565b820191906000526020600020905b81548152906001019060200180831161160157829003601f168201915b505050505081565b6000808080808080803332146116775760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610b74565b63ffffffff89161561175c5763ffffffff8916600090815260076020908152604080832060089092529091206116ad8c8c612a77565b6001600160a01b038d1660009081526006602052604090206001908101548482015491840154600b548f936001600160401b03169163ffffffff600160401b90910416906001600160801b0316611703600a5490565b60018901546001600160401b0316611726576002546001600160801b031661173c565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611776565b6117658a612ae1565b975097509750975097509750975097505b9295985092959890939650565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3360009081526009602052604081205460ff1661180b5760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610b74565b60055463ffffffff16600081815260076020526040902060010154600160401b90046001600160401b0316151580611847575061184781612caf565b6118935760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610b74565b60006118a08260016140da565b90506118ab81612d2e565b63ffffffff1692915050565b63ffffffff80821660009081526007602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611940575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b815250906119865760405162461bcd60e51b8152600401610b749190614023565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006119cd8263ffffffff101590565b156119eb575063ffffffff1660009081526007602052604090205490565b506000919050565b6000611a038263ffffffff101590565b156119eb575063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031690565b60008051602061435d833981519152611a4c81611dc3565b600b546002546001600160801b03918216918491611a6a911661259c565b611a7490836141e3565b1015611ac25760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610b74565b611acc8484612a17565b610d4c6109ab565b600082815260208190526040902060010154611aef81611dc3565b610af58383612537565b6001600160a01b03828116600090815260066020526040902060020154620100009004163314611b645760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610b74565b6001600160a01b0382811660008181526006602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b6000806000806000611bfe600560049054906101000a900463ffffffff1663ffffffff166118b7565b945094509450945094509091929394565b6060610a726001600160a01b03831660145b60606000611c3083600261415d565b611c3b9060026140c2565b6001600160401b03811115611c5257611c52614346565b6040519080825280601f01601f191660200182016040528015611c7c576020820181803683370190505b509050600360fc1b81600081518110611c9757611c97614330565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611cc657611cc6614330565b60200101906001600160f81b031916908160001a9053506000611cea84600261415d565b611cf59060016140c2565b90505b6001811115611d6d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611d2957611d29614330565b1a60f81b828281518110611d3f57611d3f614330565b60200101906001600160f81b031916908160001a90535060049490941c93611d6681614243565b9050611cf8565b508315611dbc5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b74565b9392505050565b611dcd8133612e04565b50565b6001600160a01b03821660009081526006602052604090205460055460609163ffffffff600160801b9091048116911681611e3957604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050610a72565b8363ffffffff168263ffffffff161115611e8557604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050610a72565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160a01b909204161015611ef4576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050610a72565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160c01b9092041610611f62576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050610a72565b8063ffffffff168463ffffffff1614158015611f945750611f848160016140da565b63ffffffff168463ffffffff1614155b8015611fa75750611fa58482612e5d565b155b15611feb576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050610a72565b8363ffffffff16600114158015612012575061201061200b6001866141fa565b612eae565b155b15612056576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050610a72565b505092915050565b61206781612ee8565b61206e5750565b3360009081526006602052604090205460025463ffffffff600160e01b9092048216916120a391600160c01b900416826140c2565b8263ffffffff16111580156120b757508015155b156120c0575050565b6120c982612f14565b50336000908152600660205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff808216600090815260086020526040902060010154166121635760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610b74565b63ffffffff8116600081815260086020908152604080832080546001808201835591855283852001879055338085526006909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff8082166000908152600860205260408120600181015490549192839264010000000090920416111561221e57506000928392509050565b63ffffffff8316600090815260086020908152604080832080548251818502810185019093528083526122849383018282801561227a57602002820191906000526020600020905b815481526020019060010190808311612266575b505050505061309f565b63ffffffff851660008181526007602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556005805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260086020908152604091829020600101548251808401909352600b546001600160801b03808216808652600160801b909204811693850193909352600160601b909104909116919061239f9083906141bb565b6001600160801b0316815260208101516123ba908390614097565b6001600160801b03908116602083810182905283518316600160801b90920291909117600b55336000908152600690915260409020546123fc91849116614097565b3360009081526006602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff8082166000908152600860205260409020600181015490549116111561247e5750565b63ffffffff811660009081526008602052604081209061249e8282613b4f565b5060010180546001600160e01b031916905550565b6124bd8282611783565b610a3d576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556124f33390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6125418282611783565b15610a3d576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600060026125a9600a5490565b6125b69060ff168461415d565b610a72919061415d565b6125c98161315f565b61260a5760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610b74565b60055461261e9063ffffffff1660016140da565b6001600160a01b0382166000908152600660205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600a6001612667600a5490565b60ff1661267491906141e3565b8154811061268457612684614330565b6000918252602080832091909101546001600160a01b0385811680855260069093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600a80549293509091839190839081106126f6576126f6614330565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a8054806127355761273561431a565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61279b8261315f565b156127e15760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610b74565b6001600160a01b03811661282f5760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610b74565b6001600160a01b0382811660009081526006602052604090206002015462010000900416158061288457506001600160a01b038281166000908152600660205260409020600201546201000090048116908216145b6128d05760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610b74565b6128d98261318a565b6001600160a01b03838116600081815260066020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600a80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612a64576040519150601f19603f3d011682016040523d82523d6000602084013e612a69565b606091505b5050905080610af557600080fd5b63ffffffff81166000908152600760205260408120600101546001600160401b031615612ad75763ffffffff8083166000908152600860205260409020600101541615155b8015612ad05750612acd8383611dd0565b51155b9050610a72565b612abc83836131e2565b6001600160a01b0381166000908152600660205260408120600554815483928392839283928392839283927f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df929091849163ffffffff908116600160c01b909204161480612b6a575060055463ffffffff90811660009081526008602052604090206001015416155b600554909150612b7f9063ffffffff16612eae565b8015612b885750805b15612bdc57600554612ba19063ffffffff1660016140da565b63ffffffff81166000908152600760205260409020600254919b506001600160801b0390911694509250612bd58c8b6131e2565b9a50612c21565b60055463ffffffff9081166000818152600760209081526040808320600890925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b612c2b8c8b611dd0565b5115612c365760009a505b6001808301548482015463ffffffff808e16600090815260086020526040902090930154600b548f948f94936001600160401b031692600160401b900416906001600160801b0316612c87600a5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526007602090815260408083206001908101546008909352908320015491926001600160401b0390911691600160401b9004168115801590612d03575060008163ffffffff16115b8015612d26575042612d1b63ffffffff8316846140f9565b6001600160401b0316105b949350505050565b612d3781612ee8565b612d3e5750565b3360009081526009602052604090205463ffffffff650100000000008204811691612d709161010090910416826140c2565b8263ffffffff161180612d81575080155b612dc35760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610b74565b612dcc82612f14565b50336000908152600960205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b612e0e8282611783565b610a3d57612e1b81611c0f565b612e26836020611c21565b604051602001612e37929190613f61565b60408051601f198184030181529082905262461bcd60e51b8252610b7491600401614023565b600063ffffffff8216612e718460016140da565b63ffffffff16148015611dbc57505063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031615919050565b63ffffffff8116600090815260076020526040812060010154600160401b90046001600160401b0316151580610a725750610a7282612caf565b600554600090612eff9063ffffffff1660016140da565b63ffffffff168263ffffffff16149050919050565b612f27612f226001836141fa565b613236565b6005805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526008845291208151805192938493612fb29284920190613b6d565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526007845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b600081516000106130eb5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610b74565b815160006130fa600283614149565b90506131076002836142c4565b6131485760008061312f868261311e6001886141e3565b6131296001886141e3565b876132f9565b909250905061313e82826133f1565b9695505050505050565b612d268460006131596001866141e3565b84613489565b6001600160a01b0316600090815260066020526040902054600160a01b900463ffffffff9081161490565b60055460009063ffffffff1680158015906131cc57506001600160a01b03831660009081526006602052604090205463ffffffff828116600160a01b90920416145b156131d75792915050565b611dbc8160016140da565b6001600160a01b03821660009081526006602052604081205460025463ffffffff600160e01b90920482169161322091600160c01b900416826140c2565b8363ffffffff161180612d265750159392505050565b61323f81612caf565b6132465750565b60006132536001836141fa565b63ffffffff818116600090815260076020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b03160217909355600890529081209192506132e38282613b4f565b5060010180546001600160e01b03191690555050565b60008082841061330857600080fd5b8386111580156133185750848411155b61332157600080fd5b8286111580156133315750848311155b61333a57600080fd5b600761334687876141e3565b101561336257613359878787878761352e565b915091506133e7565b600061336f888888613978565b9050808411613380578095506133e1565b8481101561339a576133938160016140c2565b96506133e1565b8085111580156133a957508381105b6133b5576133b56142d8565b6133c188888388613489565b92506133d9886133d28360016140c2565b8887613489565b9150506133e7565b5061333a565b9550959350505050565b600080831280156134025750600082135b8061341857506000831380156134185750600082125b156134335760026134298484613aa8565b612ad0919061411b565b6000600261344181856142b0565b61344c6002876142b0565b6134569190614056565b613460919061411b565b9050612d2661348361347360028761411b565b61347e60028761411b565b613aa8565b82613aa8565b60008184111561349857600080fd5b828211156134a557600080fd5b8284101561350a5760076134b985856141e3565b10156134d85760006134ce868686868761352e565b509150612d269050565b60006134e5868686613978565b90508083116134f657809350613504565b6135018160016140c2565b94505b506134a5565b84848151811061351c5761351c614330565b60200260200101519050949350505050565b600080808661353e8760016140c2565b61354891906141e3565b905060008861355789836140c2565b8151811061356757613567614330565b60200260200101519050600082600110613588576001600160ff1b036135ad565b896135948a60016140c2565b815181106135a4576135a4614330565b60200260200101515b90506000836002106135c6576001600160ff1b036135eb565b8a6135d28b60026140c2565b815181106135e2576135e2614330565b60200260200101515b9050600084600310613604576001600160ff1b03613629565b8b6136108c60036140c2565b8151811061362057613620614330565b60200260200101515b9050600085600410613642576001600160ff1b03613667565b8c61364e8d60046140c2565b8151811061365e5761365e614330565b60200260200101515b9050600086600510613680576001600160ff1b036136a5565b8d61368c8e60056140c2565b8151811061369c5761369c614330565b60200260200101515b90506000876006106136be576001600160ff1b036136e3565b8e6136ca8f60066140c2565b815181106136da576136da614330565b60200260200101515b9050858713156136f1579495945b838513156136fd579293925b81831315613709579091905b84871315613715579395935b83861315613721579294925b8083131561372b57915b84861315613737579394935b8082131561374157905b8287131561374d579195915b81861315613759579094905b8085131561376357935b8286131561376f579194915b8084131561377957925b82851315613785579193915b81841315613791579092905b8284131561379d579192915b60006137a98f8e6141e3565b9050806137b857879a50613859565b80600114156137c957869a50613859565b80600214156137da57859a50613859565b80600314156137eb57849a50613859565b80600414156137fc57839a50613859565b806005141561380d57829a50613859565b806006141561381e57819a50613859565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610b74565b60008f8d61386791906141e3565b90508c8e141561388457508a99506133e798505050505050505050565b8061389b57509698506133e7975050505050505050565b80600114156138b657509598506133e7975050505050505050565b80600214156138d157509498506133e7975050505050505050565b80600314156138ec57509398506133e7975050505050505050565b806004141561390757509298506133e7975050505050505050565b806005141561392257509198506133e7975050505050505050565b806006141561393d57509098506133e7975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610b74565b60008084600261398885876140c2565b6139929190614149565b815181106139a2576139a2614330565b602002602001015190506001846139b991906141e3565b93506139c66001846140c2565b92505b6139d46001856140c2565b9350808585815181106139e9576139e9614330565b6020026020010151126139c9575b613a026001846141e3565b925080858481518110613a1757613a17614330565b6020026020010151136139f75782841015613a9f57848381518110613a3e57613a3e614330565b6020026020010151858581518110613a5857613a58614330565b6020026020010151868681518110613a7257613a72614330565b60200260200101878681518110613a8b57613a8b614330565b6020908102919091010191909152526139c9565b50909392505050565b6000808212158015613aca5750613ac6826001600160ff1b0361417c565b8313155b80613aed5750600082128015613aed5750613ae982600160ff1b61417c565b8312155b613b435760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610b74565b6000612d268385614056565b5080546000825590600052602060002090810190611dcd9190613bb8565b828054828255906000526020600020908101928215613ba8579160200282015b82811115613ba8578251825591602001919060010190613b8d565b50613bb4929150613bb8565b5090565b5b80821115613bb45760008155600101613bb9565b80356001600160a01b0381168114613be457600080fd5b919050565b60008083601f840112613bfb57600080fd5b5081356001600160401b03811115613c1257600080fd5b6020830191508360208260051b8501011115613c2d57600080fd5b9250929050565b803563ffffffff81168114613be457600080fd5b600060208284031215613c5a57600080fd5b611dbc82613bcd565b60008060408385031215613c7657600080fd5b613c7f83613bcd565b9150613c8d60208401613bcd565b90509250929050565b600080600060608486031215613cab57600080fd5b613cb484613bcd565b9250613cc260208501613bcd565b9150604084013590509250925092565b600080600060608486031215613ce757600080fd5b613cf084613bcd565b925060208401358015158114613d0557600080fd5b9150613d1360408501613c34565b90509250925092565b60008060408385031215613d2f57600080fd5b613d3883613bcd565b946020939093013593505050565b60008060408385031215613d5957600080fd5b613d6283613bcd565b9150613c8d60208401613c34565b600080600080600080600080600060c08a8c031215613d8e57600080fd5b89356001600160401b0380821115613da557600080fd5b613db18d838e01613be9565b909b50995060208c0135915080821115613dca57600080fd5b613dd68d838e01613be9565b909950975060408c0135915080821115613def57600080fd5b50613dfc8c828d01613be9565b9096509450613e0f905060608b01613c34565b9250613e1d60808b01613c34565b9150613e2b60a08b01613c34565b90509295985092959850929598565b600060208284031215613e4c57600080fd5b5035919050565b60008060408385031215613e6657600080fd5b82359150613c8d60208401613bcd565b600060208284031215613e8857600080fd5b81356001600160e01b031981168114611dbc57600080fd5b600080600080600060a08688031215613eb857600080fd5b85356001600160801b0381168114613ecf57600080fd5b9450613edd60208701613c34565b9350613eeb60408701613c34565b9250613ef960608701613c34565b9150613f0760808701613c34565b90509295509295909350565b60008060408385031215613f2657600080fd5b50508035926020909101359150565b600060208284031215613f4757600080fd5b813569ffffffffffffffffffff81168114611dbc57600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613f99816017850160208801614217565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613fca816028840160208801614217565b01602801949350505050565b6020808252825182820181905260009190848201906040850190845b818110156140175783516001600160a01b031683529284019291840191600101613ff2565b50909695505050505050565b6020815260008251806020840152614042816040850160208701614217565b601f01601f19169190910160400192915050565b600080821280156001600160ff1b0384900385131615614078576140786142ee565b600160ff1b8390038412811615614091576140916142ee565b50500190565b60006001600160801b038083168185168083038211156140b9576140b96142ee565b01949350505050565b600082198211156140d5576140d56142ee565b500190565b600063ffffffff8083168185168083038211156140b9576140b96142ee565b60006001600160401b038083168185168083038211156140b9576140b96142ee565b60008261412a5761412a614304565b600160ff1b821460001984141615614144576141446142ee565b500590565b60008261415857614158614304565b500490565b6000816000190483118215151615614177576141776142ee565b500290565b60008083128015600160ff1b85018412161561419a5761419a6142ee565b6001600160ff1b03840183138116156141b5576141b56142ee565b50500390565b60006001600160801b03838116908316818110156141db576141db6142ee565b039392505050565b6000828210156141f5576141f56142ee565b500390565b600063ffffffff838116908316818110156141db576141db6142ee565b60005b8381101561423257818101518382015260200161421a565b83811115610d4c5750506000910152565b600081614252576142526142ee565b506000190190565b600181811c9082168061426e57607f821691505b6020821081141561428f57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156142a9576142a96142ee565b5060010190565b6000826142bf576142bf614304565b500790565b6000826142d3576142d3614304565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a264697066735822122021470be6152be4514a3f635c753dab9e9730a2af627a2e3982fc7fbe2804d4be64736f6c63430008060033a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775000000000000000000000000000000000000000000000000000009184e72a0000000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016e360000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000185052494345204645454420555344432f55534420544553540000000000000000

Deployed ByteCode

0x60806040526004361061026b5760003560e01c806364efb22b11610144578063a217fddf116100b6578063c93745001161007a578063c9374500146108ce578063d4cc54e4146108f2578063d547741f14610917578063e2e4031714610937578063e9ee6eeb14610976578063feaf968c146109965761027a565b8063a217fddf14610839578063b5ab58dc1461084e578063b633620c1461086e578063c10753291461088e578063c35905c6146108ae5761027a565b80637c2b0b21116101085780637c2b0b211461069c5780638205bf6a146106d057806388aa80e71461071557806391d148541461079257806398e5b12a146107b25780639a6fc8f5146107e25761027a565b806364efb22b146105cf578063668a0f021461061157806370dea79a146106345780637284e4161461065857806375b238fc1461067a5761027a565b80633969c20f116101dd5780634f8fc3b5116101a15780634f8fc3b51461051a57806350d25bcd1461052f57806354fd4d501461056157806358609e4414610576578063613d8fcc1461059a578063628806ef146105af5761027a565b80633969c20f1461044e5780633a5381b51461046e5780633d3d7714146104a657806340884c52146104c657806346fcff4c146104e85761027a565b8063248a9ca31161022f578063248a9ca3146103595780632f2ff15d14610389578063313ce567146103a9578063357ebb02146103d557806336568abe1461040e57806338aa4c721461042e5761027a565b806301ffc9a7146102825780631327d3d8146102b7578063202ee0ed146102d757806320ed0275146102f757806323ca2903146103175761027a565b3661027a576102786109ab565b005b6102786109ab565b34801561028e57600080fd5b506102a261029d366004613e76565b610a41565b60405190151581526020015b60405180910390f35b3480156102c357600080fd5b506102786102d2366004613c48565b610a78565b3480156102e357600080fd5b506102786102f2366004613f13565b610afa565b34801561030357600080fd5b50610278610312366004613cd2565b610c4c565b34801561032357600080fd5b5061034b7f000000000000000000000000000000000000000000000000000000000016e36081565b6040519081526020016102ae565b34801561036557600080fd5b5061034b610374366004613e3a565b60009081526020819052604090206001015490565b34801561039557600080fd5b506102786103a4366004613e53565b610d52565b3480156103b557600080fd5b506003546103c39060ff1681565b60405160ff90911681526020016102ae565b3480156103e157600080fd5b506002546103f990600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102ae565b34801561041a57600080fd5b50610278610429366004613e53565b610d77565b34801561043a57600080fd5b50610278610449366004613ea0565b610df1565b34801561045a57600080fd5b50610278610469366004613d70565b61113d565b34801561047a57600080fd5b5060015461048e906001600160a01b031681565b6040516001600160a01b0390911681526020016102ae565b3480156104b257600080fd5b506102786104c1366004613c96565b6112f8565b3480156104d257600080fd5b506104db611455565b6040516102ae9190613fd6565b3480156104f457600080fd5b50600b546001600160801b03165b6040516001600160801b0390911681526020016102ae565b34801561052657600080fd5b506102786109ab565b34801561053b57600080fd5b50600554640100000000900463ffffffff1660009081526007602052604090205461034b565b34801561056d57600080fd5b5061034b600381565b34801561058257600080fd5b506002546103f990600160801b900463ffffffff1681565b3480156105a657600080fd5b50600a546103c3565b3480156105bb57600080fd5b506102786105ca366004613c48565b6114b7565b3480156105db57600080fd5b5061048e6105ea366004613c48565b6001600160a01b039081166000908152600660205260409020600201546201000090041690565b34801561061d57600080fd5b50600554640100000000900463ffffffff1661034b565b34801561064057600080fd5b506002546103f990600160e01b900463ffffffff1681565b34801561066457600080fd5b5061066d611598565b6040516102ae9190614023565b34801561068657600080fd5b5061034b60008051602061435d83398151915281565b3480156106a857600080fd5b5061034b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106dc57600080fd5b50600554640100000000900463ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031661034b565b34801561072157600080fd5b50610735610730366004613d46565b611626565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102ae565b34801561079e57600080fd5b506102a26107ad366004613e53565b611783565b3480156107be57600080fd5b506107c76117ac565b60405169ffffffffffffffffffff90911681526020016102ae565b3480156107ee57600080fd5b506108026107fd366004613f35565b6118b7565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102ae565b34801561084557600080fd5b5061034b600081565b34801561085a57600080fd5b5061034b610869366004613e3a565b6119bd565b34801561087a57600080fd5b5061034b610889366004613e3a565b6119f3565b34801561089a57600080fd5b506102786108a9366004613d1c565b611a34565b3480156108ba57600080fd5b50600254610502906001600160801b031681565b3480156108da57600080fd5b506002546103f990600160a01b900463ffffffff1681565b3480156108fe57600080fd5b50600b54600160801b90046001600160801b0316610502565b34801561092357600080fd5b50610278610932366004613e53565b611ad4565b34801561094357600080fd5b5061034b610952366004613c48565b6001600160a01b03166000908152600660205260409020546001600160801b031690565b34801561098257600080fd5b50610278610991366004613c63565b611af9565b3480156109a257600080fd5b50610802611bd5565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000906109e290476141e3565b82519091506001600160801b03168114610a3d57600b80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b60006001600160e01b03198216637965db0b60e01b1480610a7257506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008051602061435d833981519152610a9081611dc3565b6001546001600160a01b039081169083168114610af557600180546001600160a01b0319166001600160a01b0385811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b505050565b6000610b063384611dd0565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610b7d5760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000016e360821315610bed5760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610b74565b8051819015610c0f5760405162461bcd60e51b8152600401610b749190614023565b50610c198361205e565b610c2382846120fc565b600080610c2f856121e2565b91509150610c3c85612340565b610c4585612456565b5050505050565b60008051602061435d833981519152610c6481611dc3565b6001600160a01b03841660009081526009602052604090205460ff1615158315151415610c9057610d4c565b8215610cd7576001600160a01b0384166000908152600960205260409020805464ffffffffff191684151564ffffffff0019161761010063ffffffff851602179055610d00565b6001600160a01b0384166000908152600960205260409020805468ffffffffffffffffff191690555b60408051841515815263ffffffff841660208201526001600160a01b038616917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b50505050565b600082815260208190526040902060010154610d6d81611dc3565b610af583836124b3565b6001600160a01b0381163314610de75760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610b74565b610a3d8282612537565b60008051602061435d833981519152610e0981611dc3565b6000610e14600a5490565b60ff1690508563ffffffff168563ffffffff161015610e755760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610b74565b8463ffffffff168163ffffffff161015610ed15760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610b74565b63ffffffff81161580610eef57508363ffffffff168163ffffffff16115b610f3b5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610b74565b610f4d876001600160801b031661259c565b600b546001600160801b03161015610fa75760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610b74565b6000610fb2600a5490565b60ff1611156110115760008663ffffffff16116110115760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610b74565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f878760405161112c92919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b60008051602061435d83398151915261115581611dc3565b60005b898110156111a15761118f8b8b8381811061117557611175614330565b905060200201602081019061118a9190613c48565b6125c0565b8061119981614295565b915050611158565b508685146111f15760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610b74565b604d876111fd600a5490565b60ff1661120a91906140c2565b111561124e5760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610b74565b60005b878110156112c1576112af89898381811061126e5761126e614330565b90506020020160208101906112839190613c48565b88888481811061129557611295614330565b90506020020160208101906112aa9190613c48565b612792565b806112b981614295565b915050611251565b506002546112ec906001600160801b03811690869086908690600160e01b900463ffffffff16610df1565b50505050505050505050565b6001600160a01b038381166000908152600660205260409020600201546201000090041633146113635760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610b74565b6001600160a01b03831660009081526006602052604090205481906001600160801b039081169082168110156113db5760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610b74565b6113e582826141bb565b6001600160a01b038616600090815260066020526040902080546001600160801b0319166001600160801b03928316179055600b5461142d918491600160801b9004166141bb565b600b80546001600160801b03928316600160801b02908316179055610c459085908416612a17565b6060600a8054806020026020016040519081016040528092919081815260200182805480156114ad57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161148f575b5050505050905090565b6001600160a01b038181166000908152600660205260409020600301541633146115235760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610b74565b6001600160a01b0381166000818152600660205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b600480546115a59061425a565b80601f01602080910402602001604051908101604052809291908181526020018280546115d19061425a565b801561161e5780601f106115f35761010080835404028352916020019161161e565b820191906000526020600020905b81548152906001019060200180831161160157829003601f168201915b505050505081565b6000808080808080803332146116775760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610b74565b63ffffffff89161561175c5763ffffffff8916600090815260076020908152604080832060089092529091206116ad8c8c612a77565b6001600160a01b038d1660009081526006602052604090206001908101548482015491840154600b548f936001600160401b03169163ffffffff600160401b90910416906001600160801b0316611703600a5490565b60018901546001600160401b0316611726576002546001600160801b031661173c565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611776565b6117658a612ae1565b975097509750975097509750975097505b9295985092959890939650565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3360009081526009602052604081205460ff1661180b5760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610b74565b60055463ffffffff16600081815260076020526040902060010154600160401b90046001600160401b0316151580611847575061184781612caf565b6118935760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610b74565b60006118a08260016140da565b90506118ab81612d2e565b63ffffffff1692915050565b63ffffffff80821660009081526007602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611940575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b815250906119865760405162461bcd60e51b8152600401610b749190614023565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006119cd8263ffffffff101590565b156119eb575063ffffffff1660009081526007602052604090205490565b506000919050565b6000611a038263ffffffff101590565b156119eb575063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031690565b60008051602061435d833981519152611a4c81611dc3565b600b546002546001600160801b03918216918491611a6a911661259c565b611a7490836141e3565b1015611ac25760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610b74565b611acc8484612a17565b610d4c6109ab565b600082815260208190526040902060010154611aef81611dc3565b610af58383612537565b6001600160a01b03828116600090815260066020526040902060020154620100009004163314611b645760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610b74565b6001600160a01b0382811660008181526006602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b6000806000806000611bfe600560049054906101000a900463ffffffff1663ffffffff166118b7565b945094509450945094509091929394565b6060610a726001600160a01b03831660145b60606000611c3083600261415d565b611c3b9060026140c2565b6001600160401b03811115611c5257611c52614346565b6040519080825280601f01601f191660200182016040528015611c7c576020820181803683370190505b509050600360fc1b81600081518110611c9757611c97614330565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611cc657611cc6614330565b60200101906001600160f81b031916908160001a9053506000611cea84600261415d565b611cf59060016140c2565b90505b6001811115611d6d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611d2957611d29614330565b1a60f81b828281518110611d3f57611d3f614330565b60200101906001600160f81b031916908160001a90535060049490941c93611d6681614243565b9050611cf8565b508315611dbc5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b74565b9392505050565b611dcd8133612e04565b50565b6001600160a01b03821660009081526006602052604090205460055460609163ffffffff600160801b9091048116911681611e3957604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050610a72565b8363ffffffff168263ffffffff161115611e8557604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050610a72565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160a01b909204161015611ef4576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050610a72565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160c01b9092041610611f62576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050610a72565b8063ffffffff168463ffffffff1614158015611f945750611f848160016140da565b63ffffffff168463ffffffff1614155b8015611fa75750611fa58482612e5d565b155b15611feb576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050610a72565b8363ffffffff16600114158015612012575061201061200b6001866141fa565b612eae565b155b15612056576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050610a72565b505092915050565b61206781612ee8565b61206e5750565b3360009081526006602052604090205460025463ffffffff600160e01b9092048216916120a391600160c01b900416826140c2565b8263ffffffff16111580156120b757508015155b156120c0575050565b6120c982612f14565b50336000908152600660205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff808216600090815260086020526040902060010154166121635760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610b74565b63ffffffff8116600081815260086020908152604080832080546001808201835591855283852001879055338085526006909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff8082166000908152600860205260408120600181015490549192839264010000000090920416111561221e57506000928392509050565b63ffffffff8316600090815260086020908152604080832080548251818502810185019093528083526122849383018282801561227a57602002820191906000526020600020905b815481526020019060010190808311612266575b505050505061309f565b63ffffffff851660008181526007602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556005805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260086020908152604091829020600101548251808401909352600b546001600160801b03808216808652600160801b909204811693850193909352600160601b909104909116919061239f9083906141bb565b6001600160801b0316815260208101516123ba908390614097565b6001600160801b03908116602083810182905283518316600160801b90920291909117600b55336000908152600690915260409020546123fc91849116614097565b3360009081526006602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff8082166000908152600860205260409020600181015490549116111561247e5750565b63ffffffff811660009081526008602052604081209061249e8282613b4f565b5060010180546001600160e01b031916905550565b6124bd8282611783565b610a3d576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556124f33390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6125418282611783565b15610a3d576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600060026125a9600a5490565b6125b69060ff168461415d565b610a72919061415d565b6125c98161315f565b61260a5760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610b74565b60055461261e9063ffffffff1660016140da565b6001600160a01b0382166000908152600660205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600a6001612667600a5490565b60ff1661267491906141e3565b8154811061268457612684614330565b6000918252602080832091909101546001600160a01b0385811680855260069093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600a80549293509091839190839081106126f6576126f6614330565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a8054806127355761273561431a565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61279b8261315f565b156127e15760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610b74565b6001600160a01b03811661282f5760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610b74565b6001600160a01b0382811660009081526006602052604090206002015462010000900416158061288457506001600160a01b038281166000908152600660205260409020600201546201000090048116908216145b6128d05760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610b74565b6128d98261318a565b6001600160a01b03838116600081815260066020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600a80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612a64576040519150601f19603f3d011682016040523d82523d6000602084013e612a69565b606091505b5050905080610af557600080fd5b63ffffffff81166000908152600760205260408120600101546001600160401b031615612ad75763ffffffff8083166000908152600860205260409020600101541615155b8015612ad05750612acd8383611dd0565b51155b9050610a72565b612abc83836131e2565b6001600160a01b0381166000908152600660205260408120600554815483928392839283928392839283927f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df929091849163ffffffff908116600160c01b909204161480612b6a575060055463ffffffff90811660009081526008602052604090206001015416155b600554909150612b7f9063ffffffff16612eae565b8015612b885750805b15612bdc57600554612ba19063ffffffff1660016140da565b63ffffffff81166000908152600760205260409020600254919b506001600160801b0390911694509250612bd58c8b6131e2565b9a50612c21565b60055463ffffffff9081166000818152600760209081526040808320600890925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b612c2b8c8b611dd0565b5115612c365760009a505b6001808301548482015463ffffffff808e16600090815260086020526040902090930154600b548f948f94936001600160401b031692600160401b900416906001600160801b0316612c87600a5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526007602090815260408083206001908101546008909352908320015491926001600160401b0390911691600160401b9004168115801590612d03575060008163ffffffff16115b8015612d26575042612d1b63ffffffff8316846140f9565b6001600160401b0316105b949350505050565b612d3781612ee8565b612d3e5750565b3360009081526009602052604090205463ffffffff650100000000008204811691612d709161010090910416826140c2565b8263ffffffff161180612d81575080155b612dc35760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610b74565b612dcc82612f14565b50336000908152600960205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b612e0e8282611783565b610a3d57612e1b81611c0f565b612e26836020611c21565b604051602001612e37929190613f61565b60408051601f198184030181529082905262461bcd60e51b8252610b7491600401614023565b600063ffffffff8216612e718460016140da565b63ffffffff16148015611dbc57505063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031615919050565b63ffffffff8116600090815260076020526040812060010154600160401b90046001600160401b0316151580610a725750610a7282612caf565b600554600090612eff9063ffffffff1660016140da565b63ffffffff168263ffffffff16149050919050565b612f27612f226001836141fa565b613236565b6005805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526008845291208151805192938493612fb29284920190613b6d565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526007845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b600081516000106130eb5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610b74565b815160006130fa600283614149565b90506131076002836142c4565b6131485760008061312f868261311e6001886141e3565b6131296001886141e3565b876132f9565b909250905061313e82826133f1565b9695505050505050565b612d268460006131596001866141e3565b84613489565b6001600160a01b0316600090815260066020526040902054600160a01b900463ffffffff9081161490565b60055460009063ffffffff1680158015906131cc57506001600160a01b03831660009081526006602052604090205463ffffffff828116600160a01b90920416145b156131d75792915050565b611dbc8160016140da565b6001600160a01b03821660009081526006602052604081205460025463ffffffff600160e01b90920482169161322091600160c01b900416826140c2565b8363ffffffff161180612d265750159392505050565b61323f81612caf565b6132465750565b60006132536001836141fa565b63ffffffff818116600090815260076020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b03160217909355600890529081209192506132e38282613b4f565b5060010180546001600160e01b03191690555050565b60008082841061330857600080fd5b8386111580156133185750848411155b61332157600080fd5b8286111580156133315750848311155b61333a57600080fd5b600761334687876141e3565b101561336257613359878787878761352e565b915091506133e7565b600061336f888888613978565b9050808411613380578095506133e1565b8481101561339a576133938160016140c2565b96506133e1565b8085111580156133a957508381105b6133b5576133b56142d8565b6133c188888388613489565b92506133d9886133d28360016140c2565b8887613489565b9150506133e7565b5061333a565b9550959350505050565b600080831280156134025750600082135b8061341857506000831380156134185750600082125b156134335760026134298484613aa8565b612ad0919061411b565b6000600261344181856142b0565b61344c6002876142b0565b6134569190614056565b613460919061411b565b9050612d2661348361347360028761411b565b61347e60028761411b565b613aa8565b82613aa8565b60008184111561349857600080fd5b828211156134a557600080fd5b8284101561350a5760076134b985856141e3565b10156134d85760006134ce868686868761352e565b509150612d269050565b60006134e5868686613978565b90508083116134f657809350613504565b6135018160016140c2565b94505b506134a5565b84848151811061351c5761351c614330565b60200260200101519050949350505050565b600080808661353e8760016140c2565b61354891906141e3565b905060008861355789836140c2565b8151811061356757613567614330565b60200260200101519050600082600110613588576001600160ff1b036135ad565b896135948a60016140c2565b815181106135a4576135a4614330565b60200260200101515b90506000836002106135c6576001600160ff1b036135eb565b8a6135d28b60026140c2565b815181106135e2576135e2614330565b60200260200101515b9050600084600310613604576001600160ff1b03613629565b8b6136108c60036140c2565b8151811061362057613620614330565b60200260200101515b9050600085600410613642576001600160ff1b03613667565b8c61364e8d60046140c2565b8151811061365e5761365e614330565b60200260200101515b9050600086600510613680576001600160ff1b036136a5565b8d61368c8e60056140c2565b8151811061369c5761369c614330565b60200260200101515b90506000876006106136be576001600160ff1b036136e3565b8e6136ca8f60066140c2565b815181106136da576136da614330565b60200260200101515b9050858713156136f1579495945b838513156136fd579293925b81831315613709579091905b84871315613715579395935b83861315613721579294925b8083131561372b57915b84861315613737579394935b8082131561374157905b8287131561374d579195915b81861315613759579094905b8085131561376357935b8286131561376f579194915b8084131561377957925b82851315613785579193915b81841315613791579092905b8284131561379d579192915b60006137a98f8e6141e3565b9050806137b857879a50613859565b80600114156137c957869a50613859565b80600214156137da57859a50613859565b80600314156137eb57849a50613859565b80600414156137fc57839a50613859565b806005141561380d57829a50613859565b806006141561381e57819a50613859565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610b74565b60008f8d61386791906141e3565b90508c8e141561388457508a99506133e798505050505050505050565b8061389b57509698506133e7975050505050505050565b80600114156138b657509598506133e7975050505050505050565b80600214156138d157509498506133e7975050505050505050565b80600314156138ec57509398506133e7975050505050505050565b806004141561390757509298506133e7975050505050505050565b806005141561392257509198506133e7975050505050505050565b806006141561393d57509098506133e7975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610b74565b60008084600261398885876140c2565b6139929190614149565b815181106139a2576139a2614330565b602002602001015190506001846139b991906141e3565b93506139c66001846140c2565b92505b6139d46001856140c2565b9350808585815181106139e9576139e9614330565b6020026020010151126139c9575b613a026001846141e3565b925080858481518110613a1757613a17614330565b6020026020010151136139f75782841015613a9f57848381518110613a3e57613a3e614330565b6020026020010151858581518110613a5857613a58614330565b6020026020010151868681518110613a7257613a72614330565b60200260200101878681518110613a8b57613a8b614330565b6020908102919091010191909152526139c9565b50909392505050565b6000808212158015613aca5750613ac6826001600160ff1b0361417c565b8313155b80613aed5750600082128015613aed5750613ae982600160ff1b61417c565b8312155b613b435760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610b74565b6000612d268385614056565b5080546000825590600052602060002090810190611dcd9190613bb8565b828054828255906000526020600020908101928215613ba8579160200282015b82811115613ba8578251825591602001919060010190613b8d565b50613bb4929150613bb8565b5090565b5b80821115613bb45760008155600101613bb9565b80356001600160a01b0381168114613be457600080fd5b919050565b60008083601f840112613bfb57600080fd5b5081356001600160401b03811115613c1257600080fd5b6020830191508360208260051b8501011115613c2d57600080fd5b9250929050565b803563ffffffff81168114613be457600080fd5b600060208284031215613c5a57600080fd5b611dbc82613bcd565b60008060408385031215613c7657600080fd5b613c7f83613bcd565b9150613c8d60208401613bcd565b90509250929050565b600080600060608486031215613cab57600080fd5b613cb484613bcd565b9250613cc260208501613bcd565b9150604084013590509250925092565b600080600060608486031215613ce757600080fd5b613cf084613bcd565b925060208401358015158114613d0557600080fd5b9150613d1360408501613c34565b90509250925092565b60008060408385031215613d2f57600080fd5b613d3883613bcd565b946020939093013593505050565b60008060408385031215613d5957600080fd5b613d6283613bcd565b9150613c8d60208401613c34565b600080600080600080600080600060c08a8c031215613d8e57600080fd5b89356001600160401b0380821115613da557600080fd5b613db18d838e01613be9565b909b50995060208c0135915080821115613dca57600080fd5b613dd68d838e01613be9565b909950975060408c0135915080821115613def57600080fd5b50613dfc8c828d01613be9565b9096509450613e0f905060608b01613c34565b9250613e1d60808b01613c34565b9150613e2b60a08b01613c34565b90509295985092959850929598565b600060208284031215613e4c57600080fd5b5035919050565b60008060408385031215613e6657600080fd5b82359150613c8d60208401613bcd565b600060208284031215613e8857600080fd5b81356001600160e01b031981168114611dbc57600080fd5b600080600080600060a08688031215613eb857600080fd5b85356001600160801b0381168114613ecf57600080fd5b9450613edd60208701613c34565b9350613eeb60408701613c34565b9250613ef960608701613c34565b9150613f0760808701613c34565b90509295509295909350565b60008060408385031215613f2657600080fd5b50508035926020909101359150565b600060208284031215613f4757600080fd5b813569ffffffffffffffffffff81168114611dbc57600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613f99816017850160208801614217565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613fca816028840160208801614217565b01602801949350505050565b6020808252825182820181905260009190848201906040850190845b818110156140175783516001600160a01b031683529284019291840191600101613ff2565b50909695505050505050565b6020815260008251806020840152614042816040850160208701614217565b601f01601f19169190910160400192915050565b600080821280156001600160ff1b0384900385131615614078576140786142ee565b600160ff1b8390038412811615614091576140916142ee565b50500190565b60006001600160801b038083168185168083038211156140b9576140b96142ee565b01949350505050565b600082198211156140d5576140d56142ee565b500190565b600063ffffffff8083168185168083038211156140b9576140b96142ee565b60006001600160401b038083168185168083038211156140b9576140b96142ee565b60008261412a5761412a614304565b600160ff1b821460001984141615614144576141446142ee565b500590565b60008261415857614158614304565b500490565b6000816000190483118215151615614177576141776142ee565b500290565b60008083128015600160ff1b85018412161561419a5761419a6142ee565b6001600160ff1b03840183138116156141b5576141b56142ee565b50500390565b60006001600160801b03838116908316818110156141db576141db6142ee565b039392505050565b6000828210156141f5576141f56142ee565b500390565b600063ffffffff838116908316818110156141db576141db6142ee565b60005b8381101561423257818101518382015260200161421a565b83811115610d4c5750506000910152565b600081614252576142526142ee565b506000190190565b600181811c9082168061426e57607f821691505b6020821081141561428f57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156142a9576142a96142ee565b5060010190565b6000826142bf576142bf614304565b500790565b6000826142d3576142d3614304565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a264697066735822122021470be6152be4514a3f635c753dab9e9730a2af627a2e3982fc7fbe2804d4be64736f6c63430008060033