false
false
0

Contract Address Details

0x74f17571176c7caa79a5B45Fca1Df79D0E3454F6

Contract Name
FluxAggregator
Creator
0xbb78ef–16399b at 0x79f4d0–46017b
Balance
0.01 FTN ( )
Tokens
Fetching tokens...
Transactions
461 Transactions
Transfers
0 Transfers
Gas Used
55,063,525
Last Balance Update
5073730
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x3daecb9958cb6e64f64cbd58afb0f5f8bfe08078.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
Contract name:
FluxAggregator




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




Optimization runs
200
Verified at
2025-03-18T05:57:45.985338Z

contracts/FluxAggregator.sol

Sol2uml
new
// 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;

  int256 public tresholdPercent;

  /**
   * @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,
    int256 _minSubmissionValue,
    int256 _maxSubmissionValue,
    uint8 _decimals,
    int256 _tresholdPercent,
    string memory _description
  ) {
    _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    _setupRole(ADMIN_ROLE, msg.sender);
    updateFutureRounds(_paymentAmount, 0, 0, 0, _timeout);
    minSubmissionValue = _minSubmissionValue;
    maxSubmissionValue = _maxSubmissionValue;
    decimals = _decimals;
    tresholdPercent = _tresholdPercent;
    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));
  }
  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
    );
  }

  function setTresholdPercent(int256 _percent) external onlyRole(ADMIN_ROLE) {
    require(_percent >= 0 && _percent <= 100, "Percent is not in range");
    tresholdPercent = _percent;
  }

  /**
   * @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");
    int256 answer = latestAnswer(); 
    if(answer > 0){
      require(_submission <= answer + tresholdPercent * answer / 100 && _submission >= answer - tresholdPercent * answer / 100, "difference is too big");
    }
    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;
  }

}
        

@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
    );

}
          

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);
}
          

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":"int256","name":"_tresholdPercent","internalType":"int256"},{"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":"setTresholdPercent","inputs":[{"type":"int256","name":"_percent","internalType":"int256"}]},{"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":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"tresholdPercent","inputs":[]},{"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

Verify & Publish
0x60c06040523480156200001157600080fd5b50604051620051aa380380620051aa83398101604081905262000034916200091b565b6200004160003362000118565b6200005c6000805160206200518a8339815191523362000118565b6200006c87600080808a62000128565b608085905260a08490526003805460ff191660ff8516179055600582905580516200009f906004906020840190620007cd565b50620000b263ffffffff87164262000ab5565b6000805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c880546001600160401b03929092166801000000000000000002600160401b600160801b03199092169190911790555062000b9b95505050505050565b6200012482826200048c565b5050565b6000805160206200518a83398151915262000143816200052c565b60006200014f600b5490565b60ff1690508563ffffffff168563ffffffff161015620001b65760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064015b60405180910390fd5b8463ffffffff168163ffffffff161015620002145760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401620001ad565b63ffffffff811615806200023357508363ffffffff168163ffffffff16115b620002815760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401620001ad565b620002956001600160801b0388166200053b565b600c546001600160801b03161015620002f15760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401620001ad565b6000620002fd600b5490565b60ff1611156200035f5760008663ffffffff16116200035f5760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401620001ad565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f87876040516200047b92919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000124576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620004e83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6200053881336200056a565b50565b6000600262000549600b5490565b620005589060ff168462000a93565b62000564919062000a93565b92915050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200012457620005a981620005fa60201b62001cd41760201c565b620005bf83602062001ce66200060d821b17811c565b604051602001620005d2929190620009ca565b60408051601f198184030181529082905262461bcd60e51b8252620001ad9160040162000a43565b6060620005646001600160a01b03831660145b606060006200061e83600262000a93565b6200062b90600262000a78565b6001600160401b0381111562000645576200064562000b85565b6040519080825280601f01601f19166020018201604052801562000670576020820181803683370190505b509050600360fc1b816000815181106200068e576200068e62000b6f565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620006c057620006c062000b6f565b60200101906001600160f81b031916908160001a9053506000620006e684600262000a93565b620006f390600162000a78565b90505b600181111562000775576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106200072b576200072b62000b6f565b1a60f81b82828151811062000744576200074462000b6f565b60200101906001600160f81b031916908160001a90535060049490941c936200076d8162000b02565b9050620006f6565b508315620007c65760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620001ad565b9392505050565b828054620007db9062000b1c565b90600052602060002090601f016020900481019282620007ff57600085556200084a565b82601f106200081a57805160ff19168380011785556200084a565b828001600101855582156200084a579182015b828111156200084a5782518255916020019190600101906200082d565b50620008589291506200085c565b5090565b5b808211156200085857600081556001016200085d565b600082601f8301126200088557600080fd5b81516001600160401b0380821115620008a257620008a262000b85565b604051601f8301601f19908116603f01168101908282118183101715620008cd57620008cd62000b85565b81604052838152866020858801011115620008e757600080fd5b620008fa84602083016020890162000acf565b9695505050505050565b805160ff811681146200091657600080fd5b919050565b600080600080600080600060e0888a0312156200093757600080fd5b87516001600160801b03811681146200094f57600080fd5b602089015190975063ffffffff811681146200096a57600080fd5b604089015160608a015191975095509350620009896080890162000904565b60a089015160c08a015191945092506001600160401b03811115620009ad57600080fd5b620009bb8a828b0162000873565b91505092959891949750929550565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835162000a0481601785016020880162000acf565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835162000a3781602884016020880162000acf565b01602801949350505050565b602081526000825180602084015262000a6481604085016020870162000acf565b601f01601f19169190910160400192915050565b6000821982111562000a8e5762000a8e62000b59565b500190565b600081600019048311821515161562000ab05762000ab062000b59565b500290565b60008282101562000aca5762000aca62000b59565b500390565b60005b8381101562000aec57818101518382015260200162000ad2565b8381111562000afc576000848401525b50505050565b60008162000b145762000b1462000b59565b506000190190565b600181811c9082168062000b3157607f821691505b6020821081141562000b5357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160a0516145bb62000bcf6000396000818161033f0152610bc80152600081816106f80152610b5301526145bb6000f3fe6080604052600436106102815760003560e01c8063628806ef1161014f5780639a6fc8f5116100c1578063c93745001161007a578063c937450014610917578063d4cc54e41461093b578063d547741f14610960578063e2e4031714610980578063e9ee6eeb146109bf578063feaf968c146109df57610290565b80639a6fc8f51461082b578063a217fddf14610882578063b5ab58dc14610897578063b633620c146108b7578063c1075329146108d7578063c35905c6146108f757610290565b806375b238fc1161011357806375b238fc146106c45780637c2b0b21146106e65780638205bf6a1461071a57806388aa80e71461075e57806391d14854146107db57806398e5b12a146107fb57610290565b8063628806ef146105fa57806364efb22b1461061a578063668a0f021461065c57806370dea79a1461067e5780637284e416146106a257610290565b806336568abe116101f357806346fcff4c116101ac57806346fcff4c146105345780634f8fc3b51461056657806350d25bcd1461057b57806354fd4d50146105ac57806358609e44146105c1578063613d8fcc146105e557610290565b806336568abe1461045a57806338aa4c721461047a5780633969c20f1461049a5780633a5381b5146104ba5780633d3d7714146104f257806340884c521461051257610290565b8063248a9ca311610245578063248a9ca31461036f5780632c32dd351461039f5780632f2ff15d146103bf578063313ce567146103df578063348592e91461040b578063357ebb021461042157610290565b806301ffc9a7146102985780631327d3d8146102cd578063202ee0ed146102ed57806320ed02751461030d57806323ca29031461032d57610290565b366102905761028e6109f4565b005b61028e6109f4565b3480156102a457600080fd5b506102b86102b3366004613ffa565b610a8a565b60405190151581526020015b60405180910390f35b3480156102d957600080fd5b5061028e6102e8366004613dcc565b610ac1565b3480156102f957600080fd5b5061028e610308366004614097565b610b43565b34801561031957600080fd5b5061028e610328366004613e56565b610c95565b34801561033957600080fd5b506103617f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102c4565b34801561037b57600080fd5b5061036161038a366004613fbe565b60009081526020819052604090206001015490565b3480156103ab57600080fd5b5061028e6103ba366004613fbe565b610d9b565b3480156103cb57600080fd5b5061028e6103da366004613fd7565b610e17565b3480156103eb57600080fd5b506003546103f99060ff1681565b60405160ff90911681526020016102c4565b34801561041757600080fd5b5061036160055481565b34801561042d57600080fd5b5060025461044590600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102c4565b34801561046657600080fd5b5061028e610475366004613fd7565b610e3c565b34801561048657600080fd5b5061028e610495366004614024565b610eb6565b3480156104a657600080fd5b5061028e6104b5366004613ef4565b611202565b3480156104c657600080fd5b506001546104da906001600160a01b031681565b6040516001600160a01b0390911681526020016102c4565b3480156104fe57600080fd5b5061028e61050d366004613e1a565b6113bd565b34801561051e57600080fd5b5061052761151a565b6040516102c4919061415a565b34801561054057600080fd5b50600c546001600160801b03165b6040516001600160801b0390911681526020016102c4565b34801561057257600080fd5b5061028e6109f4565b34801561058757600080fd5b50600654600160201b900463ffffffff16600090815260086020526040902054610361565b3480156105b857600080fd5b50610361600381565b3480156105cd57600080fd5b5060025461044590600160801b900463ffffffff1681565b3480156105f157600080fd5b50600b546103f9565b34801561060657600080fd5b5061028e610615366004613dcc565b61157c565b34801561062657600080fd5b506104da610635366004613dcc565b6001600160a01b039081166000908152600760205260409020600201546201000090041690565b34801561066857600080fd5b50600654600160201b900463ffffffff16610361565b34801561068a57600080fd5b5060025461044590600160e01b900463ffffffff1681565b3480156106ae57600080fd5b506106b761165d565b6040516102c491906141a7565b3480156106d057600080fd5b5061036160008051602061456683398151915281565b3480156106f257600080fd5b506103617f000000000000000000000000000000000000000000000000000000000000000081565b34801561072657600080fd5b50600654600160201b900463ffffffff16600090815260086020526040902060010154600160401b90046001600160401b0316610361565b34801561076a57600080fd5b5061077e610779366004613eca565b6116eb565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102c4565b3480156107e757600080fd5b506102b86107f6366004613fd7565b611848565b34801561080757600080fd5b50610810611871565b60405169ffffffffffffffffffff90911681526020016102c4565b34801561083757600080fd5b5061084b6108463660046140b9565b61197c565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102c4565b34801561088e57600080fd5b50610361600081565b3480156108a357600080fd5b506103616108b2366004613fbe565b611a82565b3480156108c357600080fd5b506103616108d2366004613fbe565b611ab8565b3480156108e357600080fd5b5061028e6108f2366004613ea0565b611af9565b34801561090357600080fd5b5060025461054e906001600160801b031681565b34801561092357600080fd5b5060025461044590600160a01b900463ffffffff1681565b34801561094757600080fd5b50600c54600160801b90046001600160801b031661054e565b34801561096c57600080fd5b5061028e61097b366004613fd7565b611b99565b34801561098c57600080fd5b5061036161099b366004613dcc565b6001600160a01b03166000908152600760205260409020546001600160801b031690565b3480156109cb57600080fd5b5061028e6109da366004613de7565b611bbe565b3480156109eb57600080fd5b5061084b611c9a565b60408051808201909152600c546001600160801b038082168352600160801b9091041660208201819052600090610a2b90476143ec565b82519091506001600160801b03168114610a8657600c80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b60006001600160e01b03198216637965db0b60e01b1480610abb57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020614566833981519152610ad981611e88565b6001546001600160a01b039081169083168114610b3e57600180546001600160a01b0319166001600160a01b0385811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b505050565b6000610b4f3384611e95565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610bc65760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000821315610c365760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610bbd565b8051819015610c585760405162461bcd60e51b8152600401610bbd91906141a7565b50610c6283612123565b610c6c82846121c1565b600080610c7885612369565b91509150610c85856124c5565b610c8e856125db565b5050505050565b600080516020614566833981519152610cad81611e88565b6001600160a01b0384166000908152600a602052604090205460ff1615158315151415610cd957610d95565b8215610d20576001600160a01b0384166000908152600a60205260409020805464ffffffffff191684151564ffffffff0019161761010063ffffffff851602179055610d49565b6001600160a01b0384166000908152600a60205260409020805468ffffffffffffffffff191690555b60408051841515815263ffffffff841660208201526001600160a01b038616917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b50505050565b600080516020614566833981519152610db381611e88565b60008212158015610dc5575060648213155b610e115760405162461bcd60e51b815260206004820152601760248201527f50657263656e74206973206e6f7420696e2072616e67650000000000000000006044820152606401610bbd565b50600555565b600082815260208190526040902060010154610e3281611e88565b610b3e8383612638565b6001600160a01b0381163314610eac5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610bbd565b610a8682826126bc565b600080516020614566833981519152610ece81611e88565b6000610ed9600b5490565b60ff1690508563ffffffff168563ffffffff161015610f3a5760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610bbd565b8463ffffffff168163ffffffff161015610f965760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610bbd565b63ffffffff81161580610fb457508363ffffffff168163ffffffff16115b6110005760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610bbd565b611012876001600160801b0316612721565b600c546001600160801b0316101561106c5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610bbd565b6000611077600b5490565b60ff1611156110d65760008663ffffffff16116110d65760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610bbd565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f87876040516111f192919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b60008051602061456683398151915261121a81611e88565b60005b89811015611266576112548b8b8381811061123a5761123a614539565b905060200201602081019061124f9190613dcc565b612745565b8061125e8161449e565b91505061121d565b508685146112b65760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610bbd565b604d876112c2600b5490565b60ff166112cf9190614246565b11156113135760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610bbd565b60005b878110156113865761137489898381811061133357611333614539565b90506020020160208101906113489190613dcc565b88888481811061135a5761135a614539565b905060200201602081019061136f9190613dcc565b612917565b8061137e8161449e565b915050611316565b506002546113b1906001600160801b03811690869086908690600160e01b900463ffffffff16610eb6565b50505050505050505050565b6001600160a01b038381166000908152600760205260409020600201546201000090041633146114285760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610bbd565b6001600160a01b03831660009081526007602052604090205481906001600160801b039081169082168110156114a05760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610bbd565b6114aa82826143c4565b6001600160a01b038616600090815260076020526040902080546001600160801b0319166001600160801b03928316179055600c546114f2918491600160801b9004166143c4565b600c80546001600160801b03928316600160801b02908316179055610c8e9085908416612b9c565b6060600b80548060200260200160405190810160405280929190818152602001828054801561157257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611554575b5050505050905090565b6001600160a01b038181166000908152600760205260409020600301541633146115e85760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610bbd565b6001600160a01b0381166000818152600760205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b6004805461166a90614463565b80601f016020809104026020016040519081016040528092919081815260200182805461169690614463565b80156116e35780601f106116b8576101008083540402835291602001916116e3565b820191906000526020600020905b8154815290600101906020018083116116c657829003601f168201915b505050505081565b60008080808080808033321461173c5760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610bbd565b63ffffffff8916156118215763ffffffff8916600090815260086020908152604080832060099092529091206117728c8c612bfc565b6001600160a01b038d1660009081526007602052604090206001908101548482015491840154600c548f936001600160401b03169163ffffffff600160401b90910416906001600160801b03166117c8600b5490565b60018901546001600160401b03166117eb576002546001600160801b0316611801565b6001880154600160601b90046001600160801b03165b8363ffffffff16935099509950995099509950995099509950505061183b565b61182a8a612c66565b975097509750975097509750975097505b9295985092959890939650565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b336000908152600a602052604081205460ff166118d05760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610bbd565b60065463ffffffff16600081815260086020526040902060010154600160401b90046001600160401b031615158061190c575061190c81612e34565b6119585760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610bbd565b600061196582600161425e565b905061197081612eb3565b63ffffffff1692915050565b63ffffffff80821660009081526008602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611a05575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b81525090611a4b5760405162461bcd60e51b8152600401610bbd91906141a7565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b6000611a928263ffffffff101590565b15611ab0575063ffffffff1660009081526008602052604090205490565b506000919050565b6000611ac88263ffffffff101590565b15611ab0575063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031690565b600080516020614566833981519152611b1181611e88565b600c546002546001600160801b03918216918491611b2f9116612721565b611b3990836143ec565b1015611b875760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610bbd565b611b918484612b9c565b610d956109f4565b600082815260208190526040902060010154611bb481611e88565b610b3e83836126bc565b6001600160a01b03828116600090815260076020526040902060020154620100009004163314611c295760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610bbd565b6001600160a01b0382811660008181526007602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b6000806000806000611cc3600660049054906101000a900463ffffffff1663ffffffff1661197c565b945094509450945094509091929394565b6060610abb6001600160a01b03831660145b60606000611cf5836002614366565b611d00906002614246565b6001600160401b03811115611d1757611d1761454f565b6040519080825280601f01601f191660200182016040528015611d41576020820181803683370190505b509050600360fc1b81600081518110611d5c57611d5c614539565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611d8b57611d8b614539565b60200101906001600160f81b031916908160001a9053506000611daf846002614366565b611dba906001614246565b90505b6001811115611e32576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611dee57611dee614539565b1a60f81b828281518110611e0457611e04614539565b60200101906001600160f81b031916908160001a90535060049490941c93611e2b8161444c565b9050611dbd565b508315611e815760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610bbd565b9392505050565b611e928133612f89565b50565b6001600160a01b03821660009081526007602052604090205460065460609163ffffffff600160801b9091048116911681611efe57604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050610abb565b8363ffffffff168263ffffffff161115611f4a57604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050610abb565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160a01b909204161015611fb9576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050610abb565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160c01b9092041610612027576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050610abb565b8063ffffffff168463ffffffff1614158015612059575061204981600161425e565b63ffffffff168463ffffffff1614155b801561206c575061206a8482612fe2565b155b156120b0576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050610abb565b8363ffffffff166001141580156120d757506120d56120d0600186614403565b613033565b155b1561211b576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050610abb565b505092915050565b61212c8161306d565b6121335750565b3360009081526007602052604090205460025463ffffffff600160e01b90920482169161216891600160c01b90041682614246565b8263ffffffff161115801561217c57508015155b15612185575050565b61218e82613099565b50336000908152600760205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff808216600090815260096020526040902060010154166122285760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610bbd565b600654600160201b900463ffffffff16600090815260086020526040812054908113156122e95760648160055461225f91906142e1565b612269919061429f565b61227390826141da565b83131580156122a5575060648160055461228d91906142e1565b612297919061429f565b6122a19082614385565b8312155b6122e95760405162461bcd60e51b8152602060048201526015602482015274646966666572656e636520697320746f6f2062696760581b6044820152606401610bbd565b63ffffffff8216600081815260096020908152604080832080546001808201835591855283852001889055338085526007909352818420805463ffffffff60c01b1916600160c01b8702178155018790555190929186917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a4505050565b63ffffffff80821660009081526009602052604081206001810154905491928392600160201b9092041611156123a457506000928392509050565b63ffffffff83166000908152600960209081526040808320805482518185028101850190935280835261240a9383018282801561240057602002820191906000526020600020905b8154815260200190600101908083116123ec575b5050505050613223565b63ffffffff851660008181526008602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556006805467ffffffff000000001916600160201b86021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260096020908152604091829020600101548251808401909352600c546001600160801b03808216808652600160801b909204811693850193909352600160601b90910490911691906125249083906143c4565b6001600160801b03168152602081015161253f90839061421b565b6001600160801b03908116602083810182905283518316600160801b90920291909117600c55336000908152600790915260409020546125819184911661421b565b3360009081526007602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff808216600090815260096020526040902060018101549054911611156126035750565b63ffffffff81166000908152600960205260408120906126238282613cd3565b5060010180546001600160e01b031916905550565b6126428282611848565b610a86576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556126783390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6126c68282611848565b15610a86576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000600261272e600b5490565b61273b9060ff1684614366565b610abb9190614366565b61274e816132e3565b61278f5760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610bbd565b6006546127a39063ffffffff16600161425e565b6001600160a01b0382166000908152600760205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600b60016127ec600b5490565b60ff166127f991906143ec565b8154811061280957612809614539565b6000918252602080832091909101546001600160a01b0385811680855260079093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600b805492935090918391908390811061287b5761287b614539565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b8054806128ba576128ba614523565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b612920826132e3565b156129665760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610bbd565b6001600160a01b0381166129b45760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610bbd565b6001600160a01b03828116600090815260076020526040902060020154620100009004161580612a0957506001600160a01b038281166000908152600760205260409020600201546201000090048116908216145b612a555760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610bbd565b612a5e8261330e565b6001600160a01b03838116600081815260076020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600b80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612be9576040519150601f19603f3d011682016040523d82523d6000602084013e612bee565b606091505b5050905080610b3e57600080fd5b63ffffffff81166000908152600860205260408120600101546001600160401b031615612c5c5763ffffffff8083166000908152600960205260409020600101541615155b8015612c555750612c528383611e95565b51155b9050610abb565b612c418383613366565b6001600160a01b0381166000908152600760205260408120600654815483928392839283928392839283927f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7929091849163ffffffff908116600160c01b909204161480612cef575060065463ffffffff90811660009081526009602052604090206001015416155b600654909150612d049063ffffffff16613033565b8015612d0d5750805b15612d6157600654612d269063ffffffff16600161425e565b63ffffffff81166000908152600860205260409020600254919b506001600160801b0390911694509250612d5a8c8b613366565b9a50612da6565b60065463ffffffff9081166000818152600860209081526040808320600990925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b612db08c8b611e95565b5115612dbb5760009a505b6001808301548482015463ffffffff808e16600090815260096020526040902090930154600c548f948f94936001600160401b031692600160401b900416906001600160801b0316612e0c600b5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526008602090815260408083206001908101546009909352908320015491926001600160401b0390911691600160401b9004168115801590612e88575060008163ffffffff16115b8015612eab575042612ea063ffffffff83168461427d565b6001600160401b0316105b949350505050565b612ebc8161306d565b612ec35750565b336000908152600a602052604090205463ffffffff650100000000008204811691612ef5916101009091041682614246565b8263ffffffff161180612f06575080155b612f485760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610bbd565b612f5182613099565b50336000908152600a60205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b612f938282611848565b610a8657612fa081611cd4565b612fab836020611ce6565b604051602001612fbc9291906140e5565b60408051601f198184030181529082905262461bcd60e51b8252610bbd916004016141a7565b600063ffffffff8216612ff684600161425e565b63ffffffff16148015611e8157505063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031615919050565b63ffffffff8116600090815260086020526040812060010154600160401b90046001600160401b0316151580610abb5750610abb82612e34565b6006546000906130849063ffffffff16600161425e565b63ffffffff168263ffffffff16149050919050565b6130ac6130a7600183614403565b6133ba565b6006805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b0316608083015292835260098452912081518051929384936131379284920190613cf1565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a16600160201b0267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526008845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b6000815160001061326f5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610bbd565b8151600061327e6002836142cd565b905061328b6002836144cd565b6132cc576000806132b386826132a26001886143ec565b6132ad6001886143ec565b8761347d565b90925090506132c28282613575565b9695505050505050565b612eab8460006132dd6001866143ec565b8461360d565b6001600160a01b0316600090815260076020526040902054600160a01b900463ffffffff9081161490565b60065460009063ffffffff16801580159061335057506001600160a01b03831660009081526007602052604090205463ffffffff828116600160a01b90920416145b1561335b5792915050565b611e8181600161425e565b6001600160a01b03821660009081526007602052604081205460025463ffffffff600160e01b9092048216916133a491600160c01b90041682614246565b8363ffffffff161180612eab5750159392505050565b6133c381612e34565b6133ca5750565b60006133d7600183614403565b63ffffffff818116600090815260086020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b03160217909355600990529081209192506134678282613cd3565b5060010180546001600160e01b03191690555050565b60008082841061348c57600080fd5b83861115801561349c5750848411155b6134a557600080fd5b8286111580156134b55750848311155b6134be57600080fd5b60076134ca87876143ec565b10156134e6576134dd87878787876136b2565b9150915061356b565b60006134f3888888613afc565b905080841161350457809550613565565b8481101561351e57613517816001614246565b9650613565565b80851115801561352d57508381105b613539576135396144e1565b6135458888838861360d565b925061355d88613556836001614246565b888761360d565b91505061356b565b506134be565b9550959350505050565b600080831280156135865750600082135b8061359c575060008313801561359c5750600082125b156135b75760026135ad8484613c2c565b612c55919061429f565b600060026135c581856144b9565b6135d06002876144b9565b6135da91906141da565b6135e4919061429f565b9050612eab6136076135f760028761429f565b61360260028761429f565b613c2c565b82613c2c565b60008184111561361c57600080fd5b8282111561362957600080fd5b8284101561368e57600761363d85856143ec565b101561365c57600061365286868686876136b2565b509150612eab9050565b6000613669868686613afc565b905080831161367a57809350613688565b613685816001614246565b94505b50613629565b8484815181106136a0576136a0614539565b60200260200101519050949350505050565b60008080866136c2876001614246565b6136cc91906143ec565b90506000886136db8983614246565b815181106136eb576136eb614539565b6020026020010151905060008260011061370c576001600160ff1b03613731565b896137188a6001614246565b8151811061372857613728614539565b60200260200101515b905060008360021061374a576001600160ff1b0361376f565b8a6137568b6002614246565b8151811061376657613766614539565b60200260200101515b9050600084600310613788576001600160ff1b036137ad565b8b6137948c6003614246565b815181106137a4576137a4614539565b60200260200101515b90506000856004106137c6576001600160ff1b036137eb565b8c6137d28d6004614246565b815181106137e2576137e2614539565b60200260200101515b9050600086600510613804576001600160ff1b03613829565b8d6138108e6005614246565b8151811061382057613820614539565b60200260200101515b9050600087600610613842576001600160ff1b03613867565b8e61384e8f6006614246565b8151811061385e5761385e614539565b60200260200101515b905085871315613875579495945b83851315613881579293925b8183131561388d579091905b84871315613899579395935b838613156138a5579294925b808313156138af57915b848613156138bb579394935b808213156138c557905b828713156138d1579195915b818613156138dd579094905b808513156138e757935b828613156138f3579194915b808413156138fd57925b82851315613909579193915b81841315613915579092905b82841315613921579192915b600061392d8f8e6143ec565b90508061393c57879a506139dd565b806001141561394d57869a506139dd565b806002141561395e57859a506139dd565b806003141561396f57849a506139dd565b806004141561398057839a506139dd565b806005141561399157829a506139dd565b80600614156139a257819a506139dd565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610bbd565b60008f8d6139eb91906143ec565b90508c8e1415613a0857508a995061356b98505050505050505050565b80613a1f575096985061356b975050505050505050565b8060011415613a3a575095985061356b975050505050505050565b8060021415613a55575094985061356b975050505050505050565b8060031415613a70575093985061356b975050505050505050565b8060041415613a8b575092985061356b975050505050505050565b8060051415613aa6575091985061356b975050505050505050565b8060061415613ac1575090985061356b975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610bbd565b600080846002613b0c8587614246565b613b1691906142cd565b81518110613b2657613b26614539565b60200260200101519050600184613b3d91906143ec565b9350613b4a600184614246565b92505b613b58600185614246565b935080858581518110613b6d57613b6d614539565b602002602001015112613b4d575b613b866001846143ec565b925080858481518110613b9b57613b9b614539565b602002602001015113613b7b5782841015613c2357848381518110613bc257613bc2614539565b6020026020010151858581518110613bdc57613bdc614539565b6020026020010151868681518110613bf657613bf6614539565b60200260200101878681518110613c0f57613c0f614539565b602090810291909101019190915252613b4d565b50909392505050565b6000808212158015613c4e5750613c4a826001600160ff1b03614385565b8313155b80613c715750600082128015613c715750613c6d82600160ff1b614385565b8312155b613cc75760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610bbd565b6000612eab83856141da565b5080546000825590600052602060002090810190611e929190613d3c565b828054828255906000526020600020908101928215613d2c579160200282015b82811115613d2c578251825591602001919060010190613d11565b50613d38929150613d3c565b5090565b5b80821115613d385760008155600101613d3d565b80356001600160a01b0381168114613d6857600080fd5b919050565b60008083601f840112613d7f57600080fd5b5081356001600160401b03811115613d9657600080fd5b6020830191508360208260051b8501011115613db157600080fd5b9250929050565b803563ffffffff81168114613d6857600080fd5b600060208284031215613dde57600080fd5b611e8182613d51565b60008060408385031215613dfa57600080fd5b613e0383613d51565b9150613e1160208401613d51565b90509250929050565b600080600060608486031215613e2f57600080fd5b613e3884613d51565b9250613e4660208501613d51565b9150604084013590509250925092565b600080600060608486031215613e6b57600080fd5b613e7484613d51565b925060208401358015158114613e8957600080fd5b9150613e9760408501613db8565b90509250925092565b60008060408385031215613eb357600080fd5b613ebc83613d51565b946020939093013593505050565b60008060408385031215613edd57600080fd5b613ee683613d51565b9150613e1160208401613db8565b600080600080600080600080600060c08a8c031215613f1257600080fd5b89356001600160401b0380821115613f2957600080fd5b613f358d838e01613d6d565b909b50995060208c0135915080821115613f4e57600080fd5b613f5a8d838e01613d6d565b909950975060408c0135915080821115613f7357600080fd5b50613f808c828d01613d6d565b9096509450613f93905060608b01613db8565b9250613fa160808b01613db8565b9150613faf60a08b01613db8565b90509295985092959850929598565b600060208284031215613fd057600080fd5b5035919050565b60008060408385031215613fea57600080fd5b82359150613e1160208401613d51565b60006020828403121561400c57600080fd5b81356001600160e01b031981168114611e8157600080fd5b600080600080600060a0868803121561403c57600080fd5b85356001600160801b038116811461405357600080fd5b945061406160208701613db8565b935061406f60408701613db8565b925061407d60608701613db8565b915061408b60808701613db8565b90509295509295909350565b600080604083850312156140aa57600080fd5b50508035926020909101359150565b6000602082840312156140cb57600080fd5b813569ffffffffffffffffffff81168114611e8157600080fd5b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161411d816017850160208801614420565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161414e816028840160208801614420565b01602801949350505050565b6020808252825182820181905260009190848201906040850190845b8181101561419b5783516001600160a01b031683529284019291840191600101614176565b50909695505050505050565b60208152600082518060208401526141c6816040850160208701614420565b601f01601f19169190910160400192915050565b600080821280156001600160ff1b03849003851316156141fc576141fc6144f7565b600160ff1b8390038412811615614215576142156144f7565b50500190565b60006001600160801b0380831681851680830382111561423d5761423d6144f7565b01949350505050565b60008219821115614259576142596144f7565b500190565b600063ffffffff80831681851680830382111561423d5761423d6144f7565b60006001600160401b0380831681851680830382111561423d5761423d6144f7565b6000826142ae576142ae61450d565b600160ff1b8214600019841416156142c8576142c86144f7565b500590565b6000826142dc576142dc61450d565b500490565b60006001600160ff1b0381841382841380821686840486111615614307576143076144f7565b600160ff1b6000871282811687830589121615614326576143266144f7565b60008712925087820587128484161615614342576143426144f7565b87850587128184161615614358576143586144f7565b505050929093029392505050565b6000816000190483118215151615614380576143806144f7565b500290565b60008083128015600160ff1b8501841216156143a3576143a36144f7565b6001600160ff1b03840183138116156143be576143be6144f7565b50500390565b60006001600160801b03838116908316818110156143e4576143e46144f7565b039392505050565b6000828210156143fe576143fe6144f7565b500390565b600063ffffffff838116908316818110156143e4576143e46144f7565b60005b8381101561443b578181015183820152602001614423565b83811115610d955750506000910152565b60008161445b5761445b6144f7565b506000190190565b600181811c9082168061447757607f821691505b6020821081141561449857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156144b2576144b26144f7565b5060010190565b6000826144c8576144c861450d565b500790565b6000826144dc576144dc61450d565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a2646970667358221220076aa7bed9bd0f0fca7eb41fe907fea3987552d80e51d3d98949b76163c6eefc64736f6c63430008060033a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775000000000000000000000000000000000000000000000000000009184e72a0000000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab24000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001250524943452046454544204254432f4554480000000000000000000000000000

Deployed ByteCode

0x6080604052600436106102815760003560e01c8063628806ef1161014f5780639a6fc8f5116100c1578063c93745001161007a578063c937450014610917578063d4cc54e41461093b578063d547741f14610960578063e2e4031714610980578063e9ee6eeb146109bf578063feaf968c146109df57610290565b80639a6fc8f51461082b578063a217fddf14610882578063b5ab58dc14610897578063b633620c146108b7578063c1075329146108d7578063c35905c6146108f757610290565b806375b238fc1161011357806375b238fc146106c45780637c2b0b21146106e65780638205bf6a1461071a57806388aa80e71461075e57806391d14854146107db57806398e5b12a146107fb57610290565b8063628806ef146105fa57806364efb22b1461061a578063668a0f021461065c57806370dea79a1461067e5780637284e416146106a257610290565b806336568abe116101f357806346fcff4c116101ac57806346fcff4c146105345780634f8fc3b51461056657806350d25bcd1461057b57806354fd4d50146105ac57806358609e44146105c1578063613d8fcc146105e557610290565b806336568abe1461045a57806338aa4c721461047a5780633969c20f1461049a5780633a5381b5146104ba5780633d3d7714146104f257806340884c521461051257610290565b8063248a9ca311610245578063248a9ca31461036f5780632c32dd351461039f5780632f2ff15d146103bf578063313ce567146103df578063348592e91461040b578063357ebb021461042157610290565b806301ffc9a7146102985780631327d3d8146102cd578063202ee0ed146102ed57806320ed02751461030d57806323ca29031461032d57610290565b366102905761028e6109f4565b005b61028e6109f4565b3480156102a457600080fd5b506102b86102b3366004613ffa565b610a8a565b60405190151581526020015b60405180910390f35b3480156102d957600080fd5b5061028e6102e8366004613dcc565b610ac1565b3480156102f957600080fd5b5061028e610308366004614097565b610b43565b34801561031957600080fd5b5061028e610328366004613e56565b610c95565b34801561033957600080fd5b506103617f00000000000000000000000000000000000000000000021e19e0c9bab240000081565b6040519081526020016102c4565b34801561037b57600080fd5b5061036161038a366004613fbe565b60009081526020819052604090206001015490565b3480156103ab57600080fd5b5061028e6103ba366004613fbe565b610d9b565b3480156103cb57600080fd5b5061028e6103da366004613fd7565b610e17565b3480156103eb57600080fd5b506003546103f99060ff1681565b60405160ff90911681526020016102c4565b34801561041757600080fd5b5061036160055481565b34801561042d57600080fd5b5060025461044590600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102c4565b34801561046657600080fd5b5061028e610475366004613fd7565b610e3c565b34801561048657600080fd5b5061028e610495366004614024565b610eb6565b3480156104a657600080fd5b5061028e6104b5366004613ef4565b611202565b3480156104c657600080fd5b506001546104da906001600160a01b031681565b6040516001600160a01b0390911681526020016102c4565b3480156104fe57600080fd5b5061028e61050d366004613e1a565b6113bd565b34801561051e57600080fd5b5061052761151a565b6040516102c4919061415a565b34801561054057600080fd5b50600c546001600160801b03165b6040516001600160801b0390911681526020016102c4565b34801561057257600080fd5b5061028e6109f4565b34801561058757600080fd5b50600654600160201b900463ffffffff16600090815260086020526040902054610361565b3480156105b857600080fd5b50610361600381565b3480156105cd57600080fd5b5060025461044590600160801b900463ffffffff1681565b3480156105f157600080fd5b50600b546103f9565b34801561060657600080fd5b5061028e610615366004613dcc565b61157c565b34801561062657600080fd5b506104da610635366004613dcc565b6001600160a01b039081166000908152600760205260409020600201546201000090041690565b34801561066857600080fd5b50600654600160201b900463ffffffff16610361565b34801561068a57600080fd5b5060025461044590600160e01b900463ffffffff1681565b3480156106ae57600080fd5b506106b761165d565b6040516102c491906141a7565b3480156106d057600080fd5b5061036160008051602061456683398151915281565b3480156106f257600080fd5b506103617f000000000000000000000000000000000000000000000000000000000000000081565b34801561072657600080fd5b50600654600160201b900463ffffffff16600090815260086020526040902060010154600160401b90046001600160401b0316610361565b34801561076a57600080fd5b5061077e610779366004613eca565b6116eb565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102c4565b3480156107e757600080fd5b506102b86107f6366004613fd7565b611848565b34801561080757600080fd5b50610810611871565b60405169ffffffffffffffffffff90911681526020016102c4565b34801561083757600080fd5b5061084b6108463660046140b9565b61197c565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102c4565b34801561088e57600080fd5b50610361600081565b3480156108a357600080fd5b506103616108b2366004613fbe565b611a82565b3480156108c357600080fd5b506103616108d2366004613fbe565b611ab8565b3480156108e357600080fd5b5061028e6108f2366004613ea0565b611af9565b34801561090357600080fd5b5060025461054e906001600160801b031681565b34801561092357600080fd5b5060025461044590600160a01b900463ffffffff1681565b34801561094757600080fd5b50600c54600160801b90046001600160801b031661054e565b34801561096c57600080fd5b5061028e61097b366004613fd7565b611b99565b34801561098c57600080fd5b5061036161099b366004613dcc565b6001600160a01b03166000908152600760205260409020546001600160801b031690565b3480156109cb57600080fd5b5061028e6109da366004613de7565b611bbe565b3480156109eb57600080fd5b5061084b611c9a565b60408051808201909152600c546001600160801b038082168352600160801b9091041660208201819052600090610a2b90476143ec565b82519091506001600160801b03168114610a8657600c80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b60006001600160e01b03198216637965db0b60e01b1480610abb57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020614566833981519152610ad981611e88565b6001546001600160a01b039081169083168114610b3e57600180546001600160a01b0319166001600160a01b0385811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b505050565b6000610b4f3384611e95565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610bc65760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f00000000000000000000000000000000000000000000021e19e0c9bab2400000821315610c365760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610bbd565b8051819015610c585760405162461bcd60e51b8152600401610bbd91906141a7565b50610c6283612123565b610c6c82846121c1565b600080610c7885612369565b91509150610c85856124c5565b610c8e856125db565b5050505050565b600080516020614566833981519152610cad81611e88565b6001600160a01b0384166000908152600a602052604090205460ff1615158315151415610cd957610d95565b8215610d20576001600160a01b0384166000908152600a60205260409020805464ffffffffff191684151564ffffffff0019161761010063ffffffff851602179055610d49565b6001600160a01b0384166000908152600a60205260409020805468ffffffffffffffffff191690555b60408051841515815263ffffffff841660208201526001600160a01b038616917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b50505050565b600080516020614566833981519152610db381611e88565b60008212158015610dc5575060648213155b610e115760405162461bcd60e51b815260206004820152601760248201527f50657263656e74206973206e6f7420696e2072616e67650000000000000000006044820152606401610bbd565b50600555565b600082815260208190526040902060010154610e3281611e88565b610b3e8383612638565b6001600160a01b0381163314610eac5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610bbd565b610a8682826126bc565b600080516020614566833981519152610ece81611e88565b6000610ed9600b5490565b60ff1690508563ffffffff168563ffffffff161015610f3a5760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610bbd565b8463ffffffff168163ffffffff161015610f965760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610bbd565b63ffffffff81161580610fb457508363ffffffff168163ffffffff16115b6110005760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610bbd565b611012876001600160801b0316612721565b600c546001600160801b0316101561106c5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610bbd565b6000611077600b5490565b60ff1611156110d65760008663ffffffff16116110d65760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610bbd565b86600260006101000a8154816001600160801b0302191690836001600160801b0316021790555085600260146101000a81548163ffffffff021916908363ffffffff16021790555084600260106101000a81548163ffffffff021916908363ffffffff16021790555083600260186101000a81548163ffffffff021916908363ffffffff160217905550826002601c6101000a81548163ffffffff021916908363ffffffff1602179055508463ffffffff168663ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f87876040516111f192919063ffffffff92831681529116602082015260400190565b60405180910390a450505050505050565b60008051602061456683398151915261121a81611e88565b60005b89811015611266576112548b8b8381811061123a5761123a614539565b905060200201602081019061124f9190613dcc565b612745565b8061125e8161449e565b91505061121d565b508685146112b65760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610bbd565b604d876112c2600b5490565b60ff166112cf9190614246565b11156113135760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610bbd565b60005b878110156113865761137489898381811061133357611333614539565b90506020020160208101906113489190613dcc565b88888481811061135a5761135a614539565b905060200201602081019061136f9190613dcc565b612917565b8061137e8161449e565b915050611316565b506002546113b1906001600160801b03811690869086908690600160e01b900463ffffffff16610eb6565b50505050505050505050565b6001600160a01b038381166000908152600760205260409020600201546201000090041633146114285760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610bbd565b6001600160a01b03831660009081526007602052604090205481906001600160801b039081169082168110156114a05760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610bbd565b6114aa82826143c4565b6001600160a01b038616600090815260076020526040902080546001600160801b0319166001600160801b03928316179055600c546114f2918491600160801b9004166143c4565b600c80546001600160801b03928316600160801b02908316179055610c8e9085908416612b9c565b6060600b80548060200260200160405190810160405280929190818152602001828054801561157257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611554575b5050505050905090565b6001600160a01b038181166000908152600760205260409020600301541633146115e85760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610bbd565b6001600160a01b0381166000818152600760205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b6004805461166a90614463565b80601f016020809104026020016040519081016040528092919081815260200182805461169690614463565b80156116e35780601f106116b8576101008083540402835291602001916116e3565b820191906000526020600020905b8154815290600101906020018083116116c657829003601f168201915b505050505081565b60008080808080808033321461173c5760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610bbd565b63ffffffff8916156118215763ffffffff8916600090815260086020908152604080832060099092529091206117728c8c612bfc565b6001600160a01b038d1660009081526007602052604090206001908101548482015491840154600c548f936001600160401b03169163ffffffff600160401b90910416906001600160801b03166117c8600b5490565b60018901546001600160401b03166117eb576002546001600160801b0316611801565b6001880154600160601b90046001600160801b03165b8363ffffffff16935099509950995099509950995099509950505061183b565b61182a8a612c66565b975097509750975097509750975097505b9295985092959890939650565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b336000908152600a602052604081205460ff166118d05760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610bbd565b60065463ffffffff16600081815260086020526040902060010154600160401b90046001600160401b031615158061190c575061190c81612e34565b6119585760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610bbd565b600061196582600161425e565b905061197081612eb3565b63ffffffff1692915050565b63ffffffff80821660009081526008602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611a05575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b81525090611a4b5760405162461bcd60e51b8152600401610bbd91906141a7565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b6000611a928263ffffffff101590565b15611ab0575063ffffffff1660009081526008602052604090205490565b506000919050565b6000611ac88263ffffffff101590565b15611ab0575063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031690565b600080516020614566833981519152611b1181611e88565b600c546002546001600160801b03918216918491611b2f9116612721565b611b3990836143ec565b1015611b875760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610bbd565b611b918484612b9c565b610d956109f4565b600082815260208190526040902060010154611bb481611e88565b610b3e83836126bc565b6001600160a01b03828116600090815260076020526040902060020154620100009004163314611c295760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610bbd565b6001600160a01b0382811660008181526007602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b6000806000806000611cc3600660049054906101000a900463ffffffff1663ffffffff1661197c565b945094509450945094509091929394565b6060610abb6001600160a01b03831660145b60606000611cf5836002614366565b611d00906002614246565b6001600160401b03811115611d1757611d1761454f565b6040519080825280601f01601f191660200182016040528015611d41576020820181803683370190505b509050600360fc1b81600081518110611d5c57611d5c614539565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611d8b57611d8b614539565b60200101906001600160f81b031916908160001a9053506000611daf846002614366565b611dba906001614246565b90505b6001811115611e32576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611dee57611dee614539565b1a60f81b828281518110611e0457611e04614539565b60200101906001600160f81b031916908160001a90535060049490941c93611e2b8161444c565b9050611dbd565b508315611e815760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610bbd565b9392505050565b611e928133612f89565b50565b6001600160a01b03821660009081526007602052604090205460065460609163ffffffff600160801b9091048116911681611efe57604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050610abb565b8363ffffffff168263ffffffff161115611f4a57604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050610abb565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160a01b909204161015611fb9576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050610abb565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160c01b9092041610612027576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050610abb565b8063ffffffff168463ffffffff1614158015612059575061204981600161425e565b63ffffffff168463ffffffff1614155b801561206c575061206a8482612fe2565b155b156120b0576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050610abb565b8363ffffffff166001141580156120d757506120d56120d0600186614403565b613033565b155b1561211b576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050610abb565b505092915050565b61212c8161306d565b6121335750565b3360009081526007602052604090205460025463ffffffff600160e01b90920482169161216891600160c01b90041682614246565b8263ffffffff161115801561217c57508015155b15612185575050565b61218e82613099565b50336000908152600760205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff808216600090815260096020526040902060010154166122285760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610bbd565b600654600160201b900463ffffffff16600090815260086020526040812054908113156122e95760648160055461225f91906142e1565b612269919061429f565b61227390826141da565b83131580156122a5575060648160055461228d91906142e1565b612297919061429f565b6122a19082614385565b8312155b6122e95760405162461bcd60e51b8152602060048201526015602482015274646966666572656e636520697320746f6f2062696760581b6044820152606401610bbd565b63ffffffff8216600081815260096020908152604080832080546001808201835591855283852001889055338085526007909352818420805463ffffffff60c01b1916600160c01b8702178155018790555190929186917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a4505050565b63ffffffff80821660009081526009602052604081206001810154905491928392600160201b9092041611156123a457506000928392509050565b63ffffffff83166000908152600960209081526040808320805482518185028101850190935280835261240a9383018282801561240057602002820191906000526020600020905b8154815260200190600101908083116123ec575b5050505050613223565b63ffffffff851660008181526008602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556006805467ffffffff000000001916600160201b86021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260096020908152604091829020600101548251808401909352600c546001600160801b03808216808652600160801b909204811693850193909352600160601b90910490911691906125249083906143c4565b6001600160801b03168152602081015161253f90839061421b565b6001600160801b03908116602083810182905283518316600160801b90920291909117600c55336000908152600790915260409020546125819184911661421b565b3360009081526007602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff808216600090815260096020526040902060018101549054911611156126035750565b63ffffffff81166000908152600960205260408120906126238282613cd3565b5060010180546001600160e01b031916905550565b6126428282611848565b610a86576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556126783390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6126c68282611848565b15610a86576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000600261272e600b5490565b61273b9060ff1684614366565b610abb9190614366565b61274e816132e3565b61278f5760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610bbd565b6006546127a39063ffffffff16600161425e565b6001600160a01b0382166000908152600760205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600b60016127ec600b5490565b60ff166127f991906143ec565b8154811061280957612809614539565b6000918252602080832091909101546001600160a01b0385811680855260079093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600b805492935090918391908390811061287b5761287b614539565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b8054806128ba576128ba614523565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b612920826132e3565b156129665760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610bbd565b6001600160a01b0381166129b45760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610bbd565b6001600160a01b03828116600090815260076020526040902060020154620100009004161580612a0957506001600160a01b038281166000908152600760205260409020600201546201000090048116908216145b612a555760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610bbd565b612a5e8261330e565b6001600160a01b03838116600081815260076020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600b80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612be9576040519150601f19603f3d011682016040523d82523d6000602084013e612bee565b606091505b5050905080610b3e57600080fd5b63ffffffff81166000908152600860205260408120600101546001600160401b031615612c5c5763ffffffff8083166000908152600960205260409020600101541615155b8015612c555750612c528383611e95565b51155b9050610abb565b612c418383613366565b6001600160a01b0381166000908152600760205260408120600654815483928392839283928392839283927f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7929091849163ffffffff908116600160c01b909204161480612cef575060065463ffffffff90811660009081526009602052604090206001015416155b600654909150612d049063ffffffff16613033565b8015612d0d5750805b15612d6157600654612d269063ffffffff16600161425e565b63ffffffff81166000908152600860205260409020600254919b506001600160801b0390911694509250612d5a8c8b613366565b9a50612da6565b60065463ffffffff9081166000818152600860209081526040808320600990925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b612db08c8b611e95565b5115612dbb5760009a505b6001808301548482015463ffffffff808e16600090815260096020526040902090930154600c548f948f94936001600160401b031692600160401b900416906001600160801b0316612e0c600b5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526008602090815260408083206001908101546009909352908320015491926001600160401b0390911691600160401b9004168115801590612e88575060008163ffffffff16115b8015612eab575042612ea063ffffffff83168461427d565b6001600160401b0316105b949350505050565b612ebc8161306d565b612ec35750565b336000908152600a602052604090205463ffffffff650100000000008204811691612ef5916101009091041682614246565b8263ffffffff161180612f06575080155b612f485760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610bbd565b612f5182613099565b50336000908152600a60205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b612f938282611848565b610a8657612fa081611cd4565b612fab836020611ce6565b604051602001612fbc9291906140e5565b60408051601f198184030181529082905262461bcd60e51b8252610bbd916004016141a7565b600063ffffffff8216612ff684600161425e565b63ffffffff16148015611e8157505063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031615919050565b63ffffffff8116600090815260086020526040812060010154600160401b90046001600160401b0316151580610abb5750610abb82612e34565b6006546000906130849063ffffffff16600161425e565b63ffffffff168263ffffffff16149050919050565b6130ac6130a7600183614403565b6133ba565b6006805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b0316608083015292835260098452912081518051929384936131379284920190613cf1565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a16600160201b0267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526008845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b6000815160001061326f5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610bbd565b8151600061327e6002836142cd565b905061328b6002836144cd565b6132cc576000806132b386826132a26001886143ec565b6132ad6001886143ec565b8761347d565b90925090506132c28282613575565b9695505050505050565b612eab8460006132dd6001866143ec565b8461360d565b6001600160a01b0316600090815260076020526040902054600160a01b900463ffffffff9081161490565b60065460009063ffffffff16801580159061335057506001600160a01b03831660009081526007602052604090205463ffffffff828116600160a01b90920416145b1561335b5792915050565b611e8181600161425e565b6001600160a01b03821660009081526007602052604081205460025463ffffffff600160e01b9092048216916133a491600160c01b90041682614246565b8363ffffffff161180612eab5750159392505050565b6133c381612e34565b6133ca5750565b60006133d7600183614403565b63ffffffff818116600090815260086020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b03160217909355600990529081209192506134678282613cd3565b5060010180546001600160e01b03191690555050565b60008082841061348c57600080fd5b83861115801561349c5750848411155b6134a557600080fd5b8286111580156134b55750848311155b6134be57600080fd5b60076134ca87876143ec565b10156134e6576134dd87878787876136b2565b9150915061356b565b60006134f3888888613afc565b905080841161350457809550613565565b8481101561351e57613517816001614246565b9650613565565b80851115801561352d57508381105b613539576135396144e1565b6135458888838861360d565b925061355d88613556836001614246565b888761360d565b91505061356b565b506134be565b9550959350505050565b600080831280156135865750600082135b8061359c575060008313801561359c5750600082125b156135b75760026135ad8484613c2c565b612c55919061429f565b600060026135c581856144b9565b6135d06002876144b9565b6135da91906141da565b6135e4919061429f565b9050612eab6136076135f760028761429f565b61360260028761429f565b613c2c565b82613c2c565b60008184111561361c57600080fd5b8282111561362957600080fd5b8284101561368e57600761363d85856143ec565b101561365c57600061365286868686876136b2565b509150612eab9050565b6000613669868686613afc565b905080831161367a57809350613688565b613685816001614246565b94505b50613629565b8484815181106136a0576136a0614539565b60200260200101519050949350505050565b60008080866136c2876001614246565b6136cc91906143ec565b90506000886136db8983614246565b815181106136eb576136eb614539565b6020026020010151905060008260011061370c576001600160ff1b03613731565b896137188a6001614246565b8151811061372857613728614539565b60200260200101515b905060008360021061374a576001600160ff1b0361376f565b8a6137568b6002614246565b8151811061376657613766614539565b60200260200101515b9050600084600310613788576001600160ff1b036137ad565b8b6137948c6003614246565b815181106137a4576137a4614539565b60200260200101515b90506000856004106137c6576001600160ff1b036137eb565b8c6137d28d6004614246565b815181106137e2576137e2614539565b60200260200101515b9050600086600510613804576001600160ff1b03613829565b8d6138108e6005614246565b8151811061382057613820614539565b60200260200101515b9050600087600610613842576001600160ff1b03613867565b8e61384e8f6006614246565b8151811061385e5761385e614539565b60200260200101515b905085871315613875579495945b83851315613881579293925b8183131561388d579091905b84871315613899579395935b838613156138a5579294925b808313156138af57915b848613156138bb579394935b808213156138c557905b828713156138d1579195915b818613156138dd579094905b808513156138e757935b828613156138f3579194915b808413156138fd57925b82851315613909579193915b81841315613915579092905b82841315613921579192915b600061392d8f8e6143ec565b90508061393c57879a506139dd565b806001141561394d57869a506139dd565b806002141561395e57859a506139dd565b806003141561396f57849a506139dd565b806004141561398057839a506139dd565b806005141561399157829a506139dd565b80600614156139a257819a506139dd565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610bbd565b60008f8d6139eb91906143ec565b90508c8e1415613a0857508a995061356b98505050505050505050565b80613a1f575096985061356b975050505050505050565b8060011415613a3a575095985061356b975050505050505050565b8060021415613a55575094985061356b975050505050505050565b8060031415613a70575093985061356b975050505050505050565b8060041415613a8b575092985061356b975050505050505050565b8060051415613aa6575091985061356b975050505050505050565b8060061415613ac1575090985061356b975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610bbd565b600080846002613b0c8587614246565b613b1691906142cd565b81518110613b2657613b26614539565b60200260200101519050600184613b3d91906143ec565b9350613b4a600184614246565b92505b613b58600185614246565b935080858581518110613b6d57613b6d614539565b602002602001015112613b4d575b613b866001846143ec565b925080858481518110613b9b57613b9b614539565b602002602001015113613b7b5782841015613c2357848381518110613bc257613bc2614539565b6020026020010151858581518110613bdc57613bdc614539565b6020026020010151868681518110613bf657613bf6614539565b60200260200101878681518110613c0f57613c0f614539565b602090810291909101019190915252613b4d565b50909392505050565b6000808212158015613c4e5750613c4a826001600160ff1b03614385565b8313155b80613c715750600082128015613c715750613c6d82600160ff1b614385565b8312155b613cc75760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610bbd565b6000612eab83856141da565b5080546000825590600052602060002090810190611e929190613d3c565b828054828255906000526020600020908101928215613d2c579160200282015b82811115613d2c578251825591602001919060010190613d11565b50613d38929150613d3c565b5090565b5b80821115613d385760008155600101613d3d565b80356001600160a01b0381168114613d6857600080fd5b919050565b60008083601f840112613d7f57600080fd5b5081356001600160401b03811115613d9657600080fd5b6020830191508360208260051b8501011115613db157600080fd5b9250929050565b803563ffffffff81168114613d6857600080fd5b600060208284031215613dde57600080fd5b611e8182613d51565b60008060408385031215613dfa57600080fd5b613e0383613d51565b9150613e1160208401613d51565b90509250929050565b600080600060608486031215613e2f57600080fd5b613e3884613d51565b9250613e4660208501613d51565b9150604084013590509250925092565b600080600060608486031215613e6b57600080fd5b613e7484613d51565b925060208401358015158114613e8957600080fd5b9150613e9760408501613db8565b90509250925092565b60008060408385031215613eb357600080fd5b613ebc83613d51565b946020939093013593505050565b60008060408385031215613edd57600080fd5b613ee683613d51565b9150613e1160208401613db8565b600080600080600080600080600060c08a8c031215613f1257600080fd5b89356001600160401b0380821115613f2957600080fd5b613f358d838e01613d6d565b909b50995060208c0135915080821115613f4e57600080fd5b613f5a8d838e01613d6d565b909950975060408c0135915080821115613f7357600080fd5b50613f808c828d01613d6d565b9096509450613f93905060608b01613db8565b9250613fa160808b01613db8565b9150613faf60a08b01613db8565b90509295985092959850929598565b600060208284031215613fd057600080fd5b5035919050565b60008060408385031215613fea57600080fd5b82359150613e1160208401613d51565b60006020828403121561400c57600080fd5b81356001600160e01b031981168114611e8157600080fd5b600080600080600060a0868803121561403c57600080fd5b85356001600160801b038116811461405357600080fd5b945061406160208701613db8565b935061406f60408701613db8565b925061407d60608701613db8565b915061408b60808701613db8565b90509295509295909350565b600080604083850312156140aa57600080fd5b50508035926020909101359150565b6000602082840312156140cb57600080fd5b813569ffffffffffffffffffff81168114611e8157600080fd5b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161411d816017850160208801614420565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161414e816028840160208801614420565b01602801949350505050565b6020808252825182820181905260009190848201906040850190845b8181101561419b5783516001600160a01b031683529284019291840191600101614176565b50909695505050505050565b60208152600082518060208401526141c6816040850160208701614420565b601f01601f19169190910160400192915050565b600080821280156001600160ff1b03849003851316156141fc576141fc6144f7565b600160ff1b8390038412811615614215576142156144f7565b50500190565b60006001600160801b0380831681851680830382111561423d5761423d6144f7565b01949350505050565b60008219821115614259576142596144f7565b500190565b600063ffffffff80831681851680830382111561423d5761423d6144f7565b60006001600160401b0380831681851680830382111561423d5761423d6144f7565b6000826142ae576142ae61450d565b600160ff1b8214600019841416156142c8576142c86144f7565b500590565b6000826142dc576142dc61450d565b500490565b60006001600160ff1b0381841382841380821686840486111615614307576143076144f7565b600160ff1b6000871282811687830589121615614326576143266144f7565b60008712925087820587128484161615614342576143426144f7565b87850587128184161615614358576143586144f7565b505050929093029392505050565b6000816000190483118215151615614380576143806144f7565b500290565b60008083128015600160ff1b8501841216156143a3576143a36144f7565b6001600160ff1b03840183138116156143be576143be6144f7565b50500390565b60006001600160801b03838116908316818110156143e4576143e46144f7565b039392505050565b6000828210156143fe576143fe6144f7565b500390565b600063ffffffff838116908316818110156143e4576143e46144f7565b60005b8381101561443b578181015183820152602001614423565b83811115610d955750506000910152565b60008161445b5761445b6144f7565b506000190190565b600181811c9082168061447757607f821691505b6020821081141561449857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156144b2576144b26144f7565b5060010190565b6000826144c8576144c861450d565b500790565b6000826144dc576144dc61450d565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a2646970667358221220076aa7bed9bd0f0fca7eb41fe907fea3987552d80e51d3d98949b76163c6eefc64736f6c63430008060033
<script src="{@file}"> </script>