Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- FluxAggregator
- Optimization enabled
- true
- Compiler version
- v0.8.6+commit.11564f7e
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2025-07-16T07:03:13.122085Z
Constructor Arguments
000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008f0d180000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000135052494345204645454420555344542f55534400000000000000000000000000
Arg [0] (&amp;amp;amp;lt;b&amp;amp;amp;gt;uint128&amp;amp;amp;lt;/b&amp;amp;amp;gt;) : 10000000000000 Arg [1] (&amp;amp;lt;b&amp;amp;gt;uint32&amp;amp;lt;/b&amp;amp;gt;) : 1000 Arg [2] (&amp;lt;b&amp;gt;int256&amp;lt;/b&amp;gt;) : 0 Arg [3] (&lt;b&gt;int256&lt;/b&gt;) : 150000000 Arg [4] (<b>uint8</b>) : 8 Arg [5] (<b>string</b>) : PRICE FEED USDT/USD
contracts/FluxAggregator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "./interfaces/AggregatorValidatorInterface.sol";
import "@openzeppelin/contracts/access/Ownable.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, Ownable {
struct Round {
int256 answer;
uint64 startedAt;
uint64 updatedAt;
uint32 answeredInRound;
}
struct RoundDetails {
int256[] submissions;
uint32 maxSubmissions;
uint32 minSubmissions;
uint32 timeout;
uint128 paymentAmount;
}
struct OracleStatus {
uint128 withdrawable;
uint32 startingRound;
uint32 endingRound;
uint32 lastReportedRound;
uint32 lastStartedRound;
int256 latestSubmission;
uint16 index;
address admin;
address pendingAdmin;
}
struct Requester {
bool authorized;
uint32 delay;
uint32 lastStartedRound;
}
struct Funds {
uint128 available;
uint128 allocated;
}
AggregatorValidatorInterface public validator;
// Round related params
uint128 public paymentAmount;
uint32 public maxSubmissionCount;
uint32 public minSubmissionCount;
uint32 public restartDelay;
uint32 public timeout;
uint8 public override decimals;
string public override description;
int256 immutable public minSubmissionValue;
int256 immutable public maxSubmissionValue;
uint256 constant public override version = 3;
/**
* @notice To ensure owner isn't withdrawing required funds as oracles are
* submitting updates, we enforce that the contract maintains a minimum
* reserve of RESERVE_ROUNDS * oracleCount() wFTN earmarked for payment to
* oracles. (Of course, this doesn't prevent the contract from running out of
* funds without the owner's intervention.)
*/
uint256 constant private RESERVE_ROUNDS = 2;
uint256 constant private MAX_ORACLE_COUNT = 77;
uint32 constant private ROUND_MAX = type(uint32).max;
uint256 private constant VALIDATOR_GAS_LIMIT = 100000;
// An error specific to the Aggregator V3 Interface, to prevent possible
// confusion around accidentally reading unset values as reported values.
string constant private V3_NO_DATA_ERROR = "No data present";
uint32 private reportingRoundId;
uint32 internal latestRoundId;
mapping(address => OracleStatus) private oracles;
mapping(uint32 => Round) internal rounds;
mapping(uint32 => RoundDetails) internal details;
mapping(address => Requester) internal requesters;
address[] private oracleAddresses;
Funds private recordedFunds;
event AvailableFundsUpdated(
uint256 indexed amount
);
event RoundDetailsUpdated(
uint128 indexed paymentAmount,
uint32 indexed minSubmissionCount,
uint32 indexed maxSubmissionCount,
uint32 restartDelay,
uint32 timeout // measured in seconds
);
event OraclePermissionsUpdated(
address indexed oracle,
bool indexed whitelisted
);
event OracleAdminUpdated(
address indexed oracle,
address indexed newAdmin
);
event OracleAdminUpdateRequested(
address indexed oracle,
address admin,
address newAdmin
);
event SubmissionReceived(
int256 indexed submission,
uint32 indexed round,
address indexed oracle
);
event RequesterPermissionsSet(
address indexed requester,
bool authorized,
uint32 delay
);
event ValidatorUpdated(
address indexed previous,
address indexed current
);
/**
* @notice set up the aggregator with initial configuration
* @param _paymentAmount The amount paid of FTN paid to each oracle per submission, in wei (units of 10⁻¹⁸ wFTN)
* @param _timeout is the number of seconds after the previous round that are
* allowed to lapse before allowing an oracle to skip an unfinished round
* _validator is an optional contract address for validating
* external validation of answers
* @param _minSubmissionValue is an immutable check for a lower bound of what
* submission values are accepted from an oracle
* @param _maxSubmissionValue is an immutable check for an upper bound of what
* submission values are accepted from an oracle
* @param _decimals represents the number of decimals to offset the answer by
* @param _description a short description of what is being reported
*/
constructor(
uint128 _paymentAmount,
uint32 _timeout,
// address _validator,
int256 _minSubmissionValue,
int256 _maxSubmissionValue,
uint8 _decimals,
string memory _description
) {
updateFutureRounds(_paymentAmount, 0, 0, 0, _timeout);
// setValidator(_validator);
minSubmissionValue = _minSubmissionValue;
maxSubmissionValue = _maxSubmissionValue;
decimals = _decimals;
description = _description;
rounds[0].updatedAt = uint64(block.timestamp - (uint256(_timeout)));
}
/**
* @notice called by oracles when they have witnessed a need to update
* @param _roundId is the ID of the round this submission pertains to
* @param _submission is the updated data that the oracle is submitting
*/
function submit(uint256 _roundId, int256 _submission)
external
{
bytes memory error = validateOracleRound(msg.sender, uint32(_roundId));
require(_submission >= minSubmissionValue, "value below minSubmissionValue");
require(_submission <= maxSubmissionValue, "value above maxSubmissionValue");
require(error.length == 0, string(error));
oracleInitializeNewRound(uint32(_roundId));
recordSubmission(_submission, uint32(_roundId));
(bool updated, int256 newAnswer) = updateRoundAnswer(uint32(_roundId));
payOracle(uint32(_roundId));
deleteRoundDetails(uint32(_roundId));
// TODO check this part
// if (updated) {
// validateAnswer(uint32(_roundId), newAnswer);
// }
}
fallback() external payable{
updateAvailableFunds();
}
receive() external payable{
updateAvailableFunds();
}
/**
* @notice called by the owner to remove and add new oracles as well as
* update the round related parameters that pertain to total oracle count
* @param _removed is the list of addresses for the new Oracles being removed
* @param _added is the list of addresses for the new Oracles being added
* @param _addedAdmins is the admin addresses for the new respective _added
* list. Only this address is allowed to access the respective oracle's funds
* @param _minSubmissions is the new minimum submission count for each round
* @param _maxSubmissions is the new maximum submission count for each round
* @param _restartDelay is the number of rounds an Oracle has to wait before
* they can initiate a round
*/
function changeOracles(
address[] calldata _removed,
address[] calldata _added,
address[] calldata _addedAdmins,
uint32 _minSubmissions,
uint32 _maxSubmissions,
uint32 _restartDelay
)
external
onlyOwner()
{
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
onlyOwner()
{
uint32 oracleNum = oracleCount(); // Save on storage reads
require(_maxSubmissions >= _minSubmissions, "max must equal/exceed min");
require(oracleNum >= _maxSubmissions, "max cannot exceed total");
require(oracleNum == 0 || oracleNum > _restartDelay, "delay cannot exceed total");
require(recordedFunds.available >= requiredReserve(_paymentAmount), "insufficient funds for payment");
if (oracleCount() > 0) {
require(_minSubmissions > 0, "min must be greater than 0");
}
paymentAmount = _paymentAmount;
minSubmissionCount = _minSubmissions;
maxSubmissionCount = _maxSubmissions;
restartDelay = _restartDelay;
timeout = _timeout;
emit RoundDetailsUpdated(
paymentAmount,
_minSubmissions,
_maxSubmissions,
_restartDelay,
_timeout
);
}
/**
* @notice the amount of payment yet to be withdrawn by oracles
*/
function allocatedFunds()
external
view
returns (uint128)
{
return recordedFunds.allocated;
}
/**
* @notice the amount of future funding available to oracles
*/
function availableFunds()
external
view
returns (uint128)
{
return recordedFunds.available;
}
/**
* @notice recalculate the amount of wFTN available for payouts
*/
function updateAvailableFunds()
public
{
Funds memory funds = recordedFunds;
uint256 nowAvailable = address(this).balance - (funds.allocated);
if (funds.available != nowAvailable) {
recordedFunds.available = uint128(nowAvailable);
emit AvailableFundsUpdated(nowAvailable);
}
}
/**
* @notice returns the number of oracles
*/
function oracleCount() public view returns (uint8) {
return uint8(oracleAddresses.length);
}
/**
* @notice returns an array of addresses containing the oracles on contract
*/
function getOracles() external view returns (address[] memory) {
return oracleAddresses;
}
/**
* @notice get the most recently reported answer
*
* @dev #[deprecated] Use latestRoundData instead. This does not error if no
* answer has been reached, it will simply return 0. Either wait to point to
* an already answered Aggregator or use the recommended latestRoundData
* instead which includes better verification information.
*/
function latestAnswer()
public
view
virtual
override
returns (int256)
{
return rounds[latestRoundId].answer;
}
/**
* @notice get the most recent updated at timestamp
*
* @dev #[deprecated] Use latestRoundData instead. This does not error if no
* answer has been reached, it will simply return 0. Either wait to point to
* an already answered Aggregator or use the recommended latestRoundData
* instead which includes better verification information.
*/
function latestTimestamp()
public
view
virtual
override
returns (uint256)
{
return rounds[latestRoundId].updatedAt;
}
/**
* @notice get the ID of the last updated round
*
* @dev #[deprecated] Use latestRoundData instead. This does not error if no
* answer has been reached, it will simply return 0. Either wait to point to
* an already answered Aggregator or use the recommended latestRoundData
* instead which includes better verification information.
*/
function latestRound()
public
view
virtual
override
returns (uint256)
{
return latestRoundId;
}
/**
* @notice get past rounds answers
* @param _roundId the round number to retrieve the answer for
*
* @dev #[deprecated] Use getRoundData instead. This does not error if no
* answer has been reached, it will simply return 0. Either wait to point to
* an already answered Aggregator or use the recommended getRoundData
* instead which includes better verification information.
*/
function getAnswer(uint256 _roundId)
public
view
virtual
override
returns (int256)
{
if (validRoundId(_roundId)) {
return rounds[uint32(_roundId)].answer;
}
return 0;
}
/**
* @notice get timestamp when an answer was last updated
* @param _roundId the round number to retrieve the updated timestamp for
*
* @dev #[deprecated] Use getRoundData instead. This does not error if no
* answer has been reached, it will simply return 0. Either wait to point to
* an already answered Aggregator or use the recommended getRoundData
* instead which includes better verification information.
*/
function getTimestamp(uint256 _roundId)
public
view
virtual
override
returns (uint256)
{
if (validRoundId(_roundId)) {
return rounds[uint32(_roundId)].updatedAt;
}
return 0;
}
/**
* @notice get data about a round. Consumers are encouraged to check
* that they're receiving fresh data by inspecting the updatedAt and
* answeredInRound return values.
* @param _roundId the round ID to retrieve the round data for
* @return roundId is the round ID for which data was retrieved
* @return answer is the answer for the given round
* @return startedAt is the timestamp when the round was started. This is 0
* if the round hasn't been started yet.
* @return updatedAt is the timestamp when the round last was updated (i.e.
* answer was last computed)
* @return answeredInRound is the round ID of the round in which the answer
* was computed. answeredInRound may be smaller than roundId when the round
* timed out. answeredInRound is equal to roundId when the round didn't time out
* and was completed regularly.
* @dev Note that for in-progress rounds (i.e. rounds that haven't yet received
* maxSubmissions) answer and updatedAt may change between queries.
*/
function getRoundData(uint80 _roundId)
public
view
virtual
override
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
Round memory r = rounds[uint32(_roundId)];
require(r.answeredInRound > 0 && validRoundId(_roundId), V3_NO_DATA_ERROR);
return (
_roundId,
r.answer,
r.startedAt,
r.updatedAt,
r.answeredInRound
);
}
/**
* @notice get data about the latest round. Consumers are encouraged to check
* that they're receiving fresh data by inspecting the updatedAt and
* answeredInRound return values. Consumers are encouraged to
* use this more fully featured method over the "legacy" latestRound/
* latestAnswer/latestTimestamp functions. Consumers are encouraged to check
* that they're receiving fresh data by inspecting the updatedAt and
* answeredInRound return values.
* @return roundId is the round ID for which data was retrieved
* @return answer is the answer for the given round
* @return startedAt is the timestamp when the round was started. This is 0
* if the round hasn't been started yet.
* @return updatedAt is the timestamp when the round last was updated (i.e.
* answer was last computed)
* @return answeredInRound is the round ID of the round in which the answer
* was computed. answeredInRound may be smaller than roundId when the round
* timed out. answeredInRound is equal to roundId when the round didn't time
* out and was completed regularly.
* @dev Note that for in-progress rounds (i.e. rounds that haven't yet
* received maxSubmissions) answer and updatedAt may change between queries.
*/
function latestRoundData()
public
view
virtual
override
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return getRoundData(latestRoundId);
}
/**
* @notice query the available amount of wFTN for an oracle to withdraw
*/
function withdrawablePayment(address _oracle)
external
view
returns (uint256)
{
return oracles[_oracle].withdrawable;
}
/**
* @notice Internal function to safely send FTN.
* @param to Recipient address.
* @param amount Amount of ETH to send.
*/
function _sendViaCall(
address payable to,
uint256 amount
) internal {
(bool sent, ) = to.call{value: amount} ("");
if (!sent) {
revert();
}
}
/**
* @notice transfers the oracle's wFTN to another address. Can only be called
* by the oracle's admin.
* @param _oracle is the oracle whose FTN is transferred
* @param _recipient is the address to send the FTN to
* @param _amount is the amount of FTN to send
*/
function withdrawPayment(address _oracle, address _recipient, uint256 _amount)
external
{
require(oracles[_oracle].admin == msg.sender, "only callable by admin");
uint128 amount = uint128(_amount);
uint128 available = oracles[_oracle].withdrawable;
require(available >= amount, "insufficient withdrawable funds");
oracles[_oracle].withdrawable = available - (amount);
recordedFunds.allocated = recordedFunds.allocated - (amount);
_sendViaCall(payable(_recipient), uint256(amount));
}
/**
* @notice transfers the owner's wFTN to another address
* @param _recipient is the address to send the wFTN to
* @param _amount is the amount of wFTN to send
*/
function withdrawFunds(address _recipient, uint256 _amount)
external
onlyOwner()
{
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
onlyOwner()
{
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
onlyOwner()
{
address previous = address(validator);
if (previous != _newValidator) {
validator = AggregatorValidatorInterface(_newValidator);
emit ValidatorUpdated(previous, _newValidator);
}
}
/**
* Private
*/
function initializeNewRound(uint32 _roundId)
private
{
updateTimedOutRoundInfo(_roundId - 1);
reportingRoundId = _roundId;
RoundDetails memory nextDetails = RoundDetails(
new int256[](0),
maxSubmissionCount,
minSubmissionCount,
timeout,
paymentAmount
);
details[_roundId] = nextDetails;
rounds[_roundId].startedAt = uint64(block.timestamp);
emit NewRound(_roundId, msg.sender, rounds[_roundId].startedAt);
}
function oracleInitializeNewRound(uint32 _roundId)
private
{
if (!newRound(_roundId)) return;
uint256 lastStarted = oracles[msg.sender].lastStartedRound; // cache storage reads
if (_roundId <= lastStarted + restartDelay && lastStarted != 0) return;
initializeNewRound(_roundId);
oracles[msg.sender].lastStartedRound = _roundId;
}
function requesterInitializeNewRound(uint32 _roundId)
private
{
if (!newRound(_roundId)) return;
uint256 lastStarted = requesters[msg.sender].lastStartedRound; // cache storage reads
require(_roundId > lastStarted + requesters[msg.sender].delay || lastStarted == 0, "must delay requests");
initializeNewRound(_roundId);
requesters[msg.sender].lastStartedRound = _roundId;
}
function updateTimedOutRoundInfo(uint32 _roundId)
private
{
if (!timedOut(_roundId)) return;
uint32 prevId = _roundId - 1;
rounds[_roundId].answer = rounds[prevId].answer;
rounds[_roundId].answeredInRound = rounds[prevId].answeredInRound;
rounds[_roundId].updatedAt = uint64(block.timestamp);
delete details[_roundId];
}
function eligibleForSpecificRound(address _oracle, uint32 _queriedRoundId)
private
view
returns (bool _eligible)
{
if (rounds[_queriedRoundId].startedAt > 0) {
return acceptingSubmissions(_queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
} else {
return delayed(_oracle, _queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
}
}
function oracleRoundStateSuggestRound(address _oracle)
private
view
returns (
bool _eligibleToSubmit,
uint32 _roundId,
int256 _latestSubmission,
uint64 _startedAt,
uint64 _timeout,
uint128 _availableFunds,
uint8 _oracleCount,
uint128 _paymentAmount
)
{
Round storage round = rounds[0];
OracleStatus storage oracle = oracles[_oracle];
bool shouldSupersede = oracle.lastReportedRound == reportingRoundId || !acceptingSubmissions(reportingRoundId);
// Instead of nudging oracles to submit to the next round, the inclusion of
// the shouldSupersede bool in the if condition pushes them towards
// submitting in a currently open round.
if (supersedable(reportingRoundId) && shouldSupersede) {
_roundId = reportingRoundId + 1;
round = rounds[_roundId];
_paymentAmount = paymentAmount;
_eligibleToSubmit = delayed(_oracle, _roundId);
} else {
_roundId = reportingRoundId;
round = rounds[_roundId];
_paymentAmount = details[_roundId].paymentAmount;
_eligibleToSubmit = acceptingSubmissions(_roundId);
}
if (validateOracleRound(_oracle, _roundId).length != 0) {
_eligibleToSubmit = false;
}
return (
_eligibleToSubmit,
_roundId,
oracle.latestSubmission,
round.startedAt,
details[_roundId].timeout,
recordedFunds.available,
oracleCount(),
_paymentAmount
);
}
function updateRoundAnswer(uint32 _roundId)
internal
returns (bool, int256)
{
if (details[_roundId].submissions.length < details[_roundId].minSubmissions) {
return (false, 0);
}
int256 newAnswer = Median.calculateInplace(details[_roundId].submissions);
rounds[_roundId].answer = newAnswer;
rounds[_roundId].updatedAt = uint64(block.timestamp);
rounds[_roundId].answeredInRound = _roundId;
latestRoundId = _roundId;
emit AnswerUpdated(newAnswer, _roundId, block.timestamp);
return (true, newAnswer);
}
function validateAnswer(
uint32 _roundId,
int256 _newAnswer
)
private
{
AggregatorValidatorInterface av = validator; // cache storage reads
if (address(av) == address(0)) return;
uint32 prevRound = _roundId - 1;
uint32 prevAnswerRoundId = rounds[prevRound].answeredInRound;
int256 prevRoundAnswer = rounds[prevRound].answer;
// We do not want the validator to ever prevent reporting, so we limit its
// gas usage and catch any errors that may arise.
try av.validate{gas: VALIDATOR_GAS_LIMIT}(
prevAnswerRoundId,
prevRoundAnswer,
_roundId,
_newAnswer
) {} catch {}
}
function payOracle(uint32 _roundId)
private
{
uint128 payment = details[_roundId].paymentAmount;
Funds memory funds = recordedFunds;
funds.available = funds.available - payment;
funds.allocated = funds.allocated + payment;
recordedFunds = funds;
oracles[msg.sender].withdrawable = oracles[msg.sender].withdrawable + payment;
emit AvailableFundsUpdated(funds.available);
}
function recordSubmission(int256 _submission, uint32 _roundId)
private
{
require(acceptingSubmissions(_roundId), "round not accepting submissions");
details[_roundId].submissions.push(_submission);
oracles[msg.sender].lastReportedRound = _roundId;
oracles[msg.sender].latestSubmission = _submission;
emit SubmissionReceived(_submission, _roundId, msg.sender);
}
function deleteRoundDetails(uint32 _roundId)
private
{
if (details[_roundId].submissions.length < details[_roundId].maxSubmissions) return;
delete details[_roundId];
}
function timedOut(uint32 _roundId)
private
view
returns (bool)
{
uint64 startedAt = rounds[_roundId].startedAt;
uint32 roundTimeout = details[_roundId].timeout;
return startedAt > 0 && roundTimeout > 0 && startedAt + roundTimeout < block.timestamp;
}
function getStartingRound(address _oracle)
private
view
returns (uint32)
{
uint32 currentRound = reportingRoundId;
if (currentRound != 0 && currentRound == oracles[_oracle].endingRound) {
return currentRound;
}
return currentRound + 1;
}
function previousAndCurrentUnanswered(uint32 _roundId, uint32 _rrId)
private
view
returns (bool)
{
return _roundId + 1 == _rrId && rounds[_rrId].updatedAt == 0;
}
function requiredReserve(uint256 payment)
private
view
returns (uint256)
{
return payment * oracleCount() * RESERVE_ROUNDS;
}
function addOracle(
address _oracle,
address _admin
)
private
{
require(!oracleEnabled(_oracle), "oracle already enabled");
require(_admin != address(0), "cannot set admin to 0");
require(oracles[_oracle].admin == address(0) || oracles[_oracle].admin == _admin, "owner cannot overwrite admin");
oracles[_oracle].startingRound = getStartingRound(_oracle);
oracles[_oracle].endingRound = ROUND_MAX;
oracles[_oracle].index = uint16(oracleAddresses.length);
oracleAddresses.push(_oracle);
oracles[_oracle].admin = _admin;
emit OraclePermissionsUpdated(_oracle, true);
emit OracleAdminUpdated(_oracle, _admin);
}
function removeOracle(
address _oracle
)
private
{
require(oracleEnabled(_oracle), "oracle not enabled");
oracles[_oracle].endingRound = reportingRoundId + 1;
address tail = oracleAddresses[uint256(oracleCount()) - 1];
uint16 index = oracles[_oracle].index;
oracles[tail].index = index;
delete oracles[_oracle].index;
oracleAddresses[index] = tail;
oracleAddresses.pop();
emit OraclePermissionsUpdated(_oracle, false);
}
function validateOracleRound(address _oracle, uint32 _roundId)
private
view
returns (bytes memory)
{
// cache storage reads
uint32 startingRound = oracles[_oracle].startingRound;
uint32 rrId = reportingRoundId;
if (startingRound == 0) return "not enabled oracle";
if (startingRound > _roundId) return "not yet enabled oracle";
if (oracles[_oracle].endingRound < _roundId) return "no longer allowed oracle";
if (oracles[_oracle].lastReportedRound >= _roundId) return "cannot report on previous rounds";
if (_roundId != rrId && _roundId != rrId + 1 && !previousAndCurrentUnanswered(_roundId, rrId)) return "invalid round to report";
if (_roundId != 1 && !supersedable(_roundId - 1)) return "previous round not supersedable";
}
function supersedable(uint32 _roundId)
private
view
returns (bool)
{
return rounds[_roundId].updatedAt > 0 || timedOut(_roundId);
}
function oracleEnabled(address _oracle)
private
view
returns (bool)
{
return oracles[_oracle].endingRound == ROUND_MAX;
}
function acceptingSubmissions(uint32 _roundId)
private
view
returns (bool)
{
return details[_roundId].maxSubmissions != 0;
}
function delayed(address _oracle, uint32 _roundId)
private
view
returns (bool)
{
uint256 lastStarted = oracles[_oracle].lastStartedRound;
return _roundId > lastStarted + restartDelay || lastStarted == 0;
}
function newRound(uint32 _roundId)
private
view
returns (bool)
{
return _roundId == reportingRoundId + 1;
}
function validRoundId(uint256 _roundId)
private
pure
returns (bool)
{
return _roundId <= ROUND_MAX;
}
}
contracts/interfaces/AggregatorValidatorInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface AggregatorValidatorInterface {
function validate(
uint256 previousRoundId,
int256 previousAnswer,
uint256 currentRoundId,
int256 currentAnswer
) external returns (bool);
}
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
@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;
}
}
contracts/Median.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
// import "./vendor/SafeMathChainlink.sol";
import "./SignedSafeMath.sol";
library Median {
using SignedSafeMath for int256;
int256 constant INT_MAX = type(int256).max;
/**
* @notice Returns the sorted middle, or the average of the two middle indexed items if the
* array has an even number of elements.
* @dev The list passed as an argument isn't modified.
* @dev This algorithm has expected runtime O(n), but for adversarially chosen inputs
* the runtime is O(n^2).
* @param list The list of elements to compare
*/
function calculate(int256[] memory list)
internal
pure
returns (int256)
{
return calculateInplace(copy(list));
}
/**
* @notice See documentation for function calculate.
* @dev The list passed as an argument may be permuted.
*/
function calculateInplace(int256[] memory list)
internal
pure
returns (int256)
{
require(0 < list.length, "list must not be empty");
uint256 len = list.length;
uint256 middleIndex = len / 2;
if (len % 2 == 0) {
int256 median1;
int256 median2;
(median1, median2) = quickselectTwo(list, 0, len - 1, middleIndex - 1, middleIndex);
return SignedSafeMath.avg(median1, median2);
} else {
return quickselect(list, 0, len - 1, middleIndex);
}
}
/**
* @notice Maximum length of list that shortSelectTwo can handle
*/
uint256 constant SHORTSELECTTWO_MAX_LENGTH = 7;
/**
* @notice Select the k1-th and k2-th element from list of length at most 7
* @dev Uses an optimal sorting network
*/
function shortSelectTwo(
int256[] memory list,
uint256 lo,
uint256 hi,
uint256 k1,
uint256 k2
)
private
pure
returns (int256 k1th, int256 k2th)
{
// Uses an optimal sorting network (https://en.wikipedia.org/wiki/Sorting_network)
// for lists of length 7. Network layout is taken from
// http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=7&algorithm=hibbard&output=svg
uint256 len = hi + 1 - lo;
int256 x0 = list[lo + 0];
int256 x1 = 1 < len ? list[lo + 1] : INT_MAX;
int256 x2 = 2 < len ? list[lo + 2] : INT_MAX;
int256 x3 = 3 < len ? list[lo + 3] : INT_MAX;
int256 x4 = 4 < len ? list[lo + 4] : INT_MAX;
int256 x5 = 5 < len ? list[lo + 5] : INT_MAX;
int256 x6 = 6 < len ? list[lo + 6] : INT_MAX;
if (x0 > x1) {(x0, x1) = (x1, x0);}
if (x2 > x3) {(x2, x3) = (x3, x2);}
if (x4 > x5) {(x4, x5) = (x5, x4);}
if (x0 > x2) {(x0, x2) = (x2, x0);}
if (x1 > x3) {(x1, x3) = (x3, x1);}
if (x4 > x6) {(x4, x6) = (x6, x4);}
if (x1 > x2) {(x1, x2) = (x2, x1);}
if (x5 > x6) {(x5, x6) = (x6, x5);}
if (x0 > x4) {(x0, x4) = (x4, x0);}
if (x1 > x5) {(x1, x5) = (x5, x1);}
if (x2 > x6) {(x2, x6) = (x6, x2);}
if (x1 > x4) {(x1, x4) = (x4, x1);}
if (x3 > x6) {(x3, x6) = (x6, x3);}
if (x2 > x4) {(x2, x4) = (x4, x2);}
if (x3 > x5) {(x3, x5) = (x5, x3);}
if (x3 > x4) {(x3, x4) = (x4, x3);}
uint256 index1 = k1 - lo;
if (index1 == 0) {k1th = x0;}
else if (index1 == 1) {k1th = x1;}
else if (index1 == 2) {k1th = x2;}
else if (index1 == 3) {k1th = x3;}
else if (index1 == 4) {k1th = x4;}
else if (index1 == 5) {k1th = x5;}
else if (index1 == 6) {k1th = x6;}
else {revert("k1 out of bounds");}
uint256 index2 = k2 - lo;
if (k1 == k2) {return (k1th, k1th);}
else if (index2 == 0) {return (k1th, x0);}
else if (index2 == 1) {return (k1th, x1);}
else if (index2 == 2) {return (k1th, x2);}
else if (index2 == 3) {return (k1th, x3);}
else if (index2 == 4) {return (k1th, x4);}
else if (index2 == 5) {return (k1th, x5);}
else if (index2 == 6) {return (k1th, x6);}
else {revert("k2 out of bounds");}
}
/**
* @notice Selects the k-th ranked element from list, looking only at indices between lo and hi
* (inclusive). Modifies list in-place.
*/
function quickselect(int256[] memory list, uint256 lo, uint256 hi, uint256 k)
private
pure
returns (int256 kth)
{
require(lo <= k);
require(k <= hi);
while (lo < hi) {
if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
int256 ignore;
(kth, ignore) = shortSelectTwo(list, lo, hi, k, k);
return kth;
}
uint256 pivotIndex = partition(list, lo, hi);
if (k <= pivotIndex) {
// since pivotIndex < (original hi passed to partition),
// termination is guaranteed in this case
hi = pivotIndex;
} else {
// since (original lo passed to partition) <= pivotIndex,
// termination is guaranteed in this case
lo = pivotIndex + 1;
}
}
return list[lo];
}
/**
* @notice Selects the k1-th and k2-th ranked elements from list, looking only at indices between
* lo and hi (inclusive). Modifies list in-place.
*/
function quickselectTwo(
int256[] memory list,
uint256 lo,
uint256 hi,
uint256 k1,
uint256 k2
)
internal // for testing
pure
returns (int256 k1th, int256 k2th)
{
require(k1 < k2);
require(lo <= k1 && k1 <= hi);
require(lo <= k2 && k2 <= hi);
while (true) {
if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
return shortSelectTwo(list, lo, hi, k1, k2);
}
uint256 pivotIdx = partition(list, lo, hi);
if (k2 <= pivotIdx) {
hi = pivotIdx;
} else if (pivotIdx < k1) {
lo = pivotIdx + 1;
} else {
assert(k1 <= pivotIdx && pivotIdx < k2);
k1th = quickselect(list, lo, pivotIdx, k1);
k2th = quickselect(list, pivotIdx + 1, hi, k2);
return (k1th, k2th);
}
}
}
/**
* @notice Partitions list in-place using Hoare's partitioning scheme.
* Only elements of list between indices lo and hi (inclusive) will be modified.
* Returns an index i, such that:
* - lo <= i < hi
* - forall j in [lo, i]. list[j] <= list[i]
* - forall j in [i, hi]. list[i] <= list[j]
*/
function partition(int256[] memory list, uint256 lo, uint256 hi)
private
pure
returns (uint256)
{
// We don't care about overflow of the addition, because it would require a list
// larger than any feasible computer's memory.
int256 pivot = list[(lo + hi) / 2];
lo -= 1; // this can underflow. that's intentional.
hi += 1;
while (true) {
do {
lo += 1;
} while (list[lo] < pivot);
do {
hi -= 1;
} while (list[hi] > pivot);
if (lo < hi) {
(list[lo], list[hi]) = (list[hi], list[lo]);
} else {
// Let orig_lo and orig_hi be the original values of lo and hi passed to partition.
// Then, hi < orig_hi, because hi decreases *strictly* monotonically
// in each loop iteration and
// - either list[orig_hi] > pivot, in which case the first loop iteration
// will achieve hi < orig_hi;
// - or list[orig_hi] <= pivot, in which case at least two loop iterations are
// needed:
// - lo will have to stop at least once in the interval
// [orig_lo, (orig_lo + orig_hi)/2]
// - (orig_lo + orig_hi)/2 < orig_hi
return hi;
}
}
}
/**
* @notice Makes an in-memory copy of the array passed in
* @param list Reference to the array to be copied
*/
function copy(int256[] memory list)
private
pure
returns(int256[] memory)
{
int256[] memory list2 = new int256[](list.length);
for (uint256 i = 0; i < list.length; i++) {
list2[i] = list[i];
}
return list2;
}
}
contracts/SignedSafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
library SignedSafeMath {
int256 private constant MIN_INT256 = type(int256).min;
int256 private constant MAX_INT256 = type(int256).max;
/**
* @dev Multiplies two signed integers, reverts on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
require(!(a == -1 && b == MIN_INT256), "SignedSafeMath: multiplication overflow");
int256 c = a * b;
require(c / a == b, "SignedSafeMath: multiplication overflow");
return c;
}
/**
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0, "SignedSafeMath: division by zero");
require(!(b == -1 && a == MIN_INT256), "SignedSafeMath: division overflow");
int256 c = a / b;
return c;
}
/**
* @dev Subtracts two signed integers, reverts on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
require((b >= 0 && a >= b) || (b < 0 && a > b), "SignedSafeMath: subtraction overflow");
int256 c = a - b;
return c;
}
/**
* @dev Adds two signed integers, reverts on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
require((b >= 0 && a <= MAX_INT256 - b) || (b < 0 && a >= MIN_INT256 - b), "SignedSafeMath: addition overflow");
int256 c = a + b;
return c;
}
/**
* @notice Computes average of two signed integers, ensuring that the computation
* doesn't overflow.
* @dev If the result is not an integer, it is rounded towards zero. For example,
* avg(-3, -4) = -3
*/
function avg(int256 _a, int256 _b) internal pure returns (int256) {
if ((_a < 0 && _b > 0) || (_a > 0 && _b < 0)) {
return add(_a, _b) / 2;
}
int256 remainder = (_a % 2 + _b % 2) / 2;
return add(add(_a / 2, _b / 2), remainder);
}
}
contracts/interfaces/AggregatorInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface AggregatorInterface {
function latestAnswer()
external
view
returns (
int256
);
function latestTimestamp()
external
view
returns (
uint256
);
function latestRound()
external
view
returns (
uint256
);
function getAnswer(
uint256 roundId
)
external
view
returns (
int256
);
function getTimestamp(
uint256 roundId
)
external
view
returns (
uint256
);
event AnswerUpdated(
int256 indexed current,
uint256 indexed roundId,
uint256 updatedAt
);
event NewRound(
uint256 indexed roundId,
address indexed startedBy,
uint256 startedAt
);
}
contracts/interfaces/AggregatorV2V3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "./AggregatorInterface.sol";
import "./AggregatorV3Interface.sol";
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}
contracts/interfaces/AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface AggregatorV3Interface {
function decimals()
external
view
returns (
uint8
);
function description()
external
view
returns (
string memory
);
function version()
external
view
returns (
uint256
);
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint128","name":"_paymentAmount","internalType":"uint128"},{"type":"uint32","name":"_timeout","internalType":"uint32"},{"type":"int256","name":"_minSubmissionValue","internalType":"int256"},{"type":"int256","name":"_maxSubmissionValue","internalType":"int256"},{"type":"uint8","name":"_decimals","internalType":"uint8"},{"type":"string","name":"_description","internalType":"string"}]},{"type":"event","name":"AnswerUpdated","inputs":[{"type":"int256","name":"current","internalType":"int256","indexed":true},{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"uint256","name":"updatedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AvailableFundsUpdated","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"NewRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"address","name":"startedBy","internalType":"address","indexed":true},{"type":"uint256","name":"startedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OracleAdminUpdateRequested","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"address","name":"admin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OracleAdminUpdated","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"address","name":"newAdmin","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OraclePermissionsUpdated","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true},{"type":"bool","name":"whitelisted","internalType":"bool","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","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":"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":"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":"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":"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":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"paymentAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"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":"setRequesterPermissions","inputs":[{"type":"address","name":"_requester","internalType":"address"},{"type":"bool","name":"_authorized","internalType":"bool"},{"type":"uint32","name":"_delay","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setValidator","inputs":[{"type":"address","name":"_newValidator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submit","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"},{"type":"int256","name":"_submission","internalType":"int256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferAdmin","inputs":[{"type":"address","name":"_oracle","internalType":"address"},{"type":"address","name":"_newAdmin","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAvailableFunds","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFutureRounds","inputs":[{"type":"uint128","name":"_paymentAmount","internalType":"uint128"},{"type":"uint32","name":"_minSubmissions","internalType":"uint32"},{"type":"uint32","name":"_maxSubmissions","internalType":"uint32"},{"type":"uint32","name":"_restartDelay","internalType":"uint32"},{"type":"uint32","name":"_timeout","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract AggregatorValidatorInterface"}],"name":"validator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"version","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFunds","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawPayment","inputs":[{"type":"address","name":"_oracle","internalType":"address"},{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawablePayment","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x60c06040523480156200001157600080fd5b506040516200466338038062004663833981016040819052620000349162000681565b6200003f33620000f5565b6200004f86600080808962000145565b608084905260a08390526003805460ff191660ff841617905580516200007d90600490602084019062000524565b506200009063ffffffff8616426200074f565b6000805260076020527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e080546001600160401b03929092166801000000000000000002600160401b600160801b031990921691909117905550620007d2945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6200014f62000497565b60006200015b600a5490565b60ff1690508463ffffffff168463ffffffff161015620001c25760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064015b60405180910390fd5b8363ffffffff168163ffffffff161015620002205760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401620001b9565b63ffffffff811615806200023f57508263ffffffff168163ffffffff16115b6200028d5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401620001b9565b620002a16001600160801b038716620004f5565b600b546001600160801b03161015620002fd5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401620001b9565b600062000309600a5490565b60ff1611156200036b5760008563ffffffff16116200036b5760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401620001b9565b85600260006101000a8154816001600160801b0302191690836001600160801b0316021790555084600260146101000a81548163ffffffff021916908363ffffffff16021790555083600260106101000a81548163ffffffff021916908363ffffffff16021790555082600260186101000a81548163ffffffff021916908363ffffffff160217905550816002601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f86866040516200048792919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b6000546001600160a01b03163314620004f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620001b9565b565b6000600262000503600a5490565b620005129060ff16846200072d565b6200051e91906200072d565b92915050565b828054620005329062000769565b90600052602060002090601f016020900481019282620005565760008555620005a1565b82601f106200057157805160ff1916838001178555620005a1565b82800160010185558215620005a1579182015b82811115620005a157825182559160200191906001019062000584565b50620005af929150620005b3565b5090565b5b80821115620005af5760008155600101620005b4565b600082601f830112620005dc57600080fd5b81516001600160401b0380821115620005f957620005f9620007bc565b604051601f8301601f19908116603f01168101908282118183101715620006245762000624620007bc565b816040528381526020925086838588010111156200064157600080fd5b600091505b8382101562000665578582018301518183018401529082019062000646565b83821115620006775760008385830101525b9695505050505050565b60008060008060008060c087890312156200069b57600080fd5b86516001600160801b0381168114620006b357600080fd5b602088015190965063ffffffff81168114620006ce57600080fd5b809550506040870151935060608701519250608087015160ff81168114620006f557600080fd5b60a08801519092506001600160401b038111156200071257600080fd5b6200072089828a01620005ca565b9150509295509295509295565b60008160001904831182151516156200074a576200074a620007a6565b500290565b600082821015620007645762000764620007a6565b500390565b600181811c908216806200077e57607f821691505b60208210811415620007a057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160a051613e5d62000806600039600081816102bd0152610a3b0152600081816105ca01526109c60152613e5d6000f3fe6080604052600436106102345760003560e01c8063668a0f021161012e578063b5ab58dc116100ab578063d4cc54e41161006f578063d4cc54e4146107f7578063e2e403171461081c578063e9ee6eeb1461085b578063f2fde38b1461087b578063feaf968c1461089b57610243565b8063b5ab58dc14610753578063b633620c14610773578063c107532914610793578063c35905c6146107b3578063c9374500146107d357610243565b80638205bf6a116100f25780638205bf6a146105ec57806388aa80e7146106315780638da5cb5b146106ae57806398e5b12a146106cc5780639a6fc8f5146106fc57610243565b8063668a0f021461053a57806370dea79a1461055d578063715018a6146105815780637284e416146105965780637c2b0b21146105b857610243565b80633d3d7714116101bc57806354fd4d501161018057806354fd4d501461048a57806358609e441461049f578063613d8fcc146104c3578063628806ef146104d857806364efb22b146104f857610243565b80633d3d7714146103cf57806340884c52146103ef57806346fcff4c146104115780634f8fc3b51461044357806350d25bcd1461045857610243565b8063313ce56711610203578063313ce567146102f2578063357ebb021461031e57806338aa4c72146103575780633969c20f146103775780633a5381b51461039757610243565b80631327d3d81461024b578063202ee0ed1461026b57806320ed02751461028b57806323ca2903146102ab57610243565b36610243576102416108b0565b005b6102416108b0565b34801561025757600080fd5b5061024161026636600461380c565b610946565b34801561027757600080fd5b50610241610286366004613a8a565b6109b6565b34801561029757600080fd5b506102416102a6366004613896565b610b08565b3480156102b757600080fd5b506102df7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156102fe57600080fd5b5060035461030c9060ff1681565b60405160ff90911681526020016102e9565b34801561032a57600080fd5b5060025461034290600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102e9565b34801561036357600080fd5b506102416103723660046139fe565b610bfd565b34801561038357600080fd5b50610241610392366004613934565b610f38565b3480156103a357600080fd5b506001546103b7906001600160a01b031681565b6040516001600160a01b0390911681526020016102e9565b3480156103db57600080fd5b506102416103ea36600461385a565b6110e2565b3480156103fb57600080fd5b5061040461123f565b6040516102e99190613ad8565b34801561041d57600080fd5b50600b546001600160801b03165b6040516001600160801b0390911681526020016102e9565b34801561044f57600080fd5b506102416108b0565b34801561046457600080fd5b50600554640100000000900463ffffffff166000908152600760205260409020546102df565b34801561049657600080fd5b506102df600381565b3480156104ab57600080fd5b5060025461034290600160801b900463ffffffff1681565b3480156104cf57600080fd5b50600a5461030c565b3480156104e457600080fd5b506102416104f336600461380c565b6112a1565b34801561050457600080fd5b506103b761051336600461380c565b6001600160a01b039081166000908152600660205260409020600201546201000090041690565b34801561054657600080fd5b50600554640100000000900463ffffffff166102df565b34801561056957600080fd5b5060025461034290600160e01b900463ffffffff1681565b34801561058d57600080fd5b50610241611382565b3480156105a257600080fd5b506105ab611396565b6040516102e99190613b25565b3480156105c457600080fd5b506102df7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f857600080fd5b50600554640100000000900463ffffffff16600090815260076020526040902060010154600160401b90046001600160401b03166102df565b34801561063d57600080fd5b5061065161064c36600461390a565b611424565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102e9565b3480156106ba57600080fd5b506000546001600160a01b03166103b7565b3480156106d857600080fd5b506106e1611581565b60405169ffffffffffffffffffff90911681526020016102e9565b34801561070857600080fd5b5061071c610717366004613aac565b61168c565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102e9565b34801561075f57600080fd5b506102df61076e366004613a71565b611792565b34801561077f57600080fd5b506102df61078e366004613a71565b6117c8565b34801561079f57600080fd5b506102416107ae3660046138e0565b611809565b3480156107bf57600080fd5b5060025461042b906001600160801b031681565b3480156107df57600080fd5b5060025461034290600160a01b900463ffffffff1681565b34801561080357600080fd5b50600b54600160801b90046001600160801b031661042b565b34801561082857600080fd5b506102df61083736600461380c565b6001600160a01b03166000908152600660205260409020546001600160801b031690565b34801561086757600080fd5b50610241610876366004613827565b611899565b34801561088757600080fd5b5061024161089636600461380c565b611975565b3480156108a757600080fd5b5061071c6119ee565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000906108e79047613d07565b82519091506001600160801b0316811461094257600b80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b61094e611a28565b6001546001600160a01b03908116908216811461094257600180546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35050565b60006109c23384611a82565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610a395760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000821315610aa95760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610a30565b8051819015610acb5760405162461bcd60e51b8152600401610a309190613b25565b50610ad583611d11565b610adf8284611daf565b600080610aeb85611e95565b91509150610af885611ff3565b610b0185612109565b5050505050565b610b10611a28565b6001600160a01b03831660009081526009602052604090205460ff1615158215151415610b3c57505050565b8115610b83576001600160a01b0383166000908152600960205260409020805464ffffffffff191683151564ffffffff0019161761010063ffffffff841602179055610bac565b6001600160a01b0383166000908152600960205260409020805468ffffffffffffffffff191690555b60408051831515815263ffffffff831660208201526001600160a01b038516917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b505050565b610c05611a28565b6000610c10600a5490565b60ff1690508463ffffffff168463ffffffff161015610c715760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610a30565b8363ffffffff168163ffffffff161015610ccd5760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610a30565b63ffffffff81161580610ceb57508263ffffffff168163ffffffff16115b610d375760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610a30565b610d49866001600160801b0316612166565b600b546001600160801b03161015610da35760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610a30565b6000610dae600a5490565b60ff161115610e0d5760008563ffffffff1611610e0d5760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610a30565b85600260006101000a8154816001600160801b0302191690836001600160801b0316021790555084600260146101000a81548163ffffffff021916908363ffffffff16021790555083600260106101000a81548163ffffffff021916908363ffffffff16021790555082600260186101000a81548163ffffffff021916908363ffffffff160217905550816002601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f8686604051610f2892919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b610f40611a28565b60005b88811015610f8c57610f7a8a8a83818110610f6057610f60613e11565b9050602002016020810190610f75919061380c565b61218a565b80610f8481613d76565b915050610f43565b50858414610fdc5760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610a30565b604d86610fe8600a5490565b60ff16610ff59190613be6565b11156110395760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610a30565b60005b868110156110ac5761109a88888381811061105957611059613e11565b905060200201602081019061106e919061380c565b87878481811061108057611080613e11565b9050602002016020810190611095919061380c565b61235c565b806110a481613d76565b91505061103c565b506002546110d7906001600160801b03811690859085908590600160e01b900463ffffffff16610bfd565b505050505050505050565b6001600160a01b0383811660009081526006602052604090206002015462010000900416331461114d5760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610a30565b6001600160a01b03831660009081526006602052604090205481906001600160801b039081169082168110156111c55760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610a30565b6111cf8282613cdf565b6001600160a01b038616600090815260066020526040902080546001600160801b0319166001600160801b03928316179055600b54611217918491600160801b900416613cdf565b600b80546001600160801b03928316600160801b02908316179055610b0190859084166125e1565b6060600a80548060200260200160405190810160405280929190818152602001828054801561129757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611279575b5050505050905090565b6001600160a01b0381811660009081526006602052604090206003015416331461130d5760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610a30565b6001600160a01b0381166000818152600660205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b61138a611a28565b6113946000612641565b565b600480546113a390613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546113cf90613d3b565b801561141c5780601f106113f15761010080835404028352916020019161141c565b820191906000526020600020905b8154815290600101906020018083116113ff57829003601f168201915b505050505081565b6000808080808080803332146114755760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610a30565b63ffffffff89161561155a5763ffffffff8916600090815260076020908152604080832060089092529091206114ab8c8c612691565b6001600160a01b038d1660009081526006602052604090206001908101548482015491840154600b548f936001600160401b03169163ffffffff600160401b90910416906001600160801b0316611501600a5490565b60018901546001600160401b0316611524576002546001600160801b031661153a565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611574565b6115638a6126fb565b975097509750975097509750975097505b9295985092959890939650565b3360009081526009602052604081205460ff166115e05760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610a30565b60055463ffffffff16600081815260076020526040902060010154600160401b90046001600160401b031615158061161c575061161c816128c9565b6116685760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610a30565b6000611675826001613bfe565b905061168081612948565b63ffffffff1692915050565b63ffffffff80821660009081526007602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611715575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b8152509061175b5760405162461bcd60e51b8152600401610a309190613b25565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006117a28263ffffffff101590565b156117c0575063ffffffff1660009081526007602052604090205490565b506000919050565b60006117d88263ffffffff101590565b156117c0575063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031690565b611811611a28565b600b546002546001600160801b0391821691839161182f9116612166565b6118399083613d07565b10156118875760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610a30565b61189183836125e1565b610bf86108b0565b6001600160a01b038281166000908152600660205260409020600201546201000090041633146119045760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610a30565b6001600160a01b0382811660008181526006602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b61197d611a28565b6001600160a01b0381166119e25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a30565b6119eb81612641565b50565b6000806000806000611a17600560049054906101000a900463ffffffff1663ffffffff1661168c565b945094509450945094509091929394565b6000546001600160a01b031633146113945760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a30565b6001600160a01b03821660009081526006602052604090205460055460609163ffffffff600160801b9091048116911681611aeb57604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050611d0b565b8363ffffffff168263ffffffff161115611b3757604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050611d0b565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160a01b909204161015611ba6576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050611d0b565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160c01b9092041610611c14576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050611d0b565b8063ffffffff168463ffffffff1614158015611c465750611c36816001613bfe565b63ffffffff168463ffffffff1614155b8015611c595750611c578482612a1e565b155b15611c9d576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050611d0b565b8363ffffffff16600114158015611cc45750611cc2611cbd600186613d1e565b612a72565b155b15611d08576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050611d0b565b50505b92915050565b611d1a81612aac565b611d215750565b3360009081526006602052604090205460025463ffffffff600160e01b909204821691611d5691600160c01b90041682613be6565b8263ffffffff1611158015611d6a57508015155b15611d73575050565b611d7c82612ad8565b50336000908152600660205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff80821660009081526008602052604090206001015416611e165760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610a30565b63ffffffff8116600081815260086020908152604080832080546001808201835591855283852001879055338085526006909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff80821660009081526008602052604081206001810154905491928392640100000000909204161115611ed157506000928392509050565b63ffffffff831660009081526008602090815260408083208054825181850281018501909352808352611f3793830182828015611f2d57602002820191906000526020600020905b815481526020019060010190808311611f19575b5050505050612c63565b63ffffffff851660008181526007602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556005805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260086020908152604091829020600101548251808401909352600b546001600160801b03808216808652600160801b909204811693850193909352600160601b9091049091169190612052908390613cdf565b6001600160801b03168152602081015161206d908390613bbb565b6001600160801b03908116602083810182905283518316600160801b90920291909117600b55336000908152600690915260409020546120af91849116613bbb565b3360009081526006602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff808216600090815260086020526040902060018101549054911611156121315750565b63ffffffff81166000908152600860205260408120906121518282613713565b5060010180546001600160e01b031916905550565b60006002612173600a5490565b6121809060ff1684613c81565b611d0b9190613c81565b61219381612d23565b6121d45760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610a30565b6005546121e89063ffffffff166001613bfe565b6001600160a01b0382166000908152600660205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600a6001612231600a5490565b60ff1661223e9190613d07565b8154811061224e5761224e613e11565b6000918252602080832091909101546001600160a01b0385811680855260069093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600a80549293509091839190839081106122c0576122c0613e11565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a8054806122ff576122ff613dfb565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61236582612d23565b156123ab5760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610a30565b6001600160a01b0381166123f95760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610a30565b6001600160a01b0382811660009081526006602052604090206002015462010000900416158061244e57506001600160a01b038281166000908152600660205260409020600201546201000090048116908216145b61249a5760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610a30565b6124a382612d4e565b6001600160a01b03838116600081815260066020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600a80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461262e576040519150601f19603f3d011682016040523d82523d6000602084013e612633565b606091505b5050905080610bf857600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b63ffffffff81166000908152600760205260408120600101546001600160401b0316156126f15763ffffffff8083166000908152600860205260409020600101541615155b80156126ea57506126e78383611a82565b51155b9050611d0b565b6126d68383612da6565b6001600160a01b0381166000908152600660205260408120600554815483928392839283928392839283927f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df929091849163ffffffff908116600160c01b909204161480612784575060055463ffffffff90811660009081526008602052604090206001015416155b6005549091506127999063ffffffff16612a72565b80156127a25750805b156127f6576005546127bb9063ffffffff166001613bfe565b63ffffffff81166000908152600760205260409020600254919b506001600160801b03909116945092506127ef8c8b612da6565b9a5061283b565b60055463ffffffff9081166000818152600760209081526040808320600890925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b6128458c8b611a82565b51156128505760009a505b6001808301548482015463ffffffff808e16600090815260086020526040902090930154600b548f948f94936001600160401b031692600160401b900416906001600160801b03166128a1600a5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526007602090815260408083206001908101546008909352908320015491926001600160401b0390911691600160401b900416811580159061291d575060008163ffffffff16115b801561294057504261293563ffffffff831684613c1d565b6001600160401b0316105b949350505050565b61295181612aac565b6129585750565b3360009081526009602052604090205463ffffffff65010000000000820481169161298a916101009091041682613be6565b8263ffffffff16118061299b575080155b6129dd5760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610a30565b6129e682612ad8565b50336000908152600960205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b600063ffffffff8216612a32846001613bfe565b63ffffffff16148015612a6b575063ffffffff8216600090815260076020526040902060010154600160401b90046001600160401b0316155b9392505050565b63ffffffff8116600090815260076020526040812060010154600160401b90046001600160401b0316151580611d0b5750611d0b826128c9565b600554600090612ac39063ffffffff166001613bfe565b63ffffffff168263ffffffff16149050919050565b612aeb612ae6600183613d1e565b612dfa565b6005805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526008845291208151805192938493612b769284920190613731565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526007845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b60008151600010612caf5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610a30565b81516000612cbe600283613c6d565b9050612ccb600283613da5565b612d0c57600080612cf38682612ce2600188613d07565b612ced600188613d07565b87612ebd565b9092509050612d028282612fb5565b9695505050505050565b612940846000612d1d600186613d07565b8461304d565b6001600160a01b0316600090815260066020526040902054600160a01b900463ffffffff9081161490565b60055460009063ffffffff168015801590612d9057506001600160a01b03831660009081526006602052604090205463ffffffff828116600160a01b90920416145b15612d9b5792915050565b612a6b816001613bfe565b6001600160a01b03821660009081526006602052604081205460025463ffffffff600160e01b909204821691612de491600160c01b90041682613be6565b8363ffffffff1611806129405750159392505050565b612e03816128c9565b612e0a5750565b6000612e17600183613d1e565b63ffffffff818116600090815260076020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b0316021790935560089052908120919250612ea78282613713565b5060010180546001600160e01b03191690555050565b600080828410612ecc57600080fd5b838611158015612edc5750848411155b612ee557600080fd5b828611158015612ef55750848311155b612efe57600080fd5b6007612f0a8787613d07565b1015612f2657612f1d87878787876130f2565b91509150612fab565b6000612f3388888861353c565b9050808411612f4457809550612fa5565b84811015612f5e57612f57816001613be6565b9650612fa5565b808511158015612f6d57508381105b612f7957612f79613db9565b612f858888838861304d565b9250612f9d88612f96836001613be6565b888761304d565b915050612fab565b50612efe565b9550959350505050565b60008083128015612fc65750600082135b80612fdc5750600083138015612fdc5750600082125b15612ff7576002612fed848461366c565b6126ea9190613c3f565b600060026130058185613d91565b613010600287613d91565b61301a9190613b7a565b6130249190613c3f565b9050612940613047613037600287613c3f565b613042600287613c3f565b61366c565b8261366c565b60008184111561305c57600080fd5b8282111561306957600080fd5b828410156130ce57600761307d8585613d07565b101561309c57600061309286868686876130f2565b5091506129409050565b60006130a986868661353c565b90508083116130ba578093506130c8565b6130c5816001613be6565b94505b50613069565b8484815181106130e0576130e0613e11565b60200260200101519050949350505050565b6000808086613102876001613be6565b61310c9190613d07565b905060008861311b8983613be6565b8151811061312b5761312b613e11565b6020026020010151905060008260011061314c576001600160ff1b03613171565b896131588a6001613be6565b8151811061316857613168613e11565b60200260200101515b905060008360021061318a576001600160ff1b036131af565b8a6131968b6002613be6565b815181106131a6576131a6613e11565b60200260200101515b90506000846003106131c8576001600160ff1b036131ed565b8b6131d48c6003613be6565b815181106131e4576131e4613e11565b60200260200101515b9050600085600410613206576001600160ff1b0361322b565b8c6132128d6004613be6565b8151811061322257613222613e11565b60200260200101515b9050600086600510613244576001600160ff1b03613269565b8d6132508e6005613be6565b8151811061326057613260613e11565b60200260200101515b9050600087600610613282576001600160ff1b036132a7565b8e61328e8f6006613be6565b8151811061329e5761329e613e11565b60200260200101515b9050858713156132b5579495945b838513156132c1579293925b818313156132cd579091905b848713156132d9579395935b838613156132e5579294925b808313156132ef57915b848613156132fb579394935b8082131561330557905b82871315613311579195915b8186131561331d579094905b8085131561332757935b82861315613333579194915b8084131561333d57925b82851315613349579193915b81841315613355579092905b82841315613361579192915b600061336d8f8e613d07565b90508061337c57879a5061341d565b806001141561338d57869a5061341d565b806002141561339e57859a5061341d565b80600314156133af57849a5061341d565b80600414156133c057839a5061341d565b80600514156133d157829a5061341d565b80600614156133e257819a5061341d565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610a30565b60008f8d61342b9190613d07565b90508c8e141561344857508a9950612fab98505050505050505050565b8061345f5750969850612fab975050505050505050565b806001141561347a5750959850612fab975050505050505050565b80600214156134955750949850612fab975050505050505050565b80600314156134b05750939850612fab975050505050505050565b80600414156134cb5750929850612fab975050505050505050565b80600514156134e65750919850612fab975050505050505050565b80600614156135015750909850612fab975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610a30565b60008084600261354c8587613be6565b6135569190613c6d565b8151811061356657613566613e11565b6020026020010151905060018461357d9190613d07565b935061358a600184613be6565b92505b613598600185613be6565b9350808585815181106135ad576135ad613e11565b60200260200101511261358d575b6135c6600184613d07565b9250808584815181106135db576135db613e11565b6020026020010151136135bb57828410156136635784838151811061360257613602613e11565b602002602001015185858151811061361c5761361c613e11565b602002602001015186868151811061363657613636613e11565b6020026020010187868151811061364f5761364f613e11565b60209081029190910101919091525261358d565b50909392505050565b600080821215801561368e575061368a826001600160ff1b03613ca0565b8313155b806136b157506000821280156136b157506136ad82600160ff1b613ca0565b8312155b6137075760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610a30565b60006129408385613b7a565b50805460008255906000526020600020908101906119eb919061377c565b82805482825590600052602060002090810192821561376c579160200282015b8281111561376c578251825591602001919060010190613751565b5061377892915061377c565b5090565b5b80821115613778576000815560010161377d565b80356001600160a01b03811681146137a857600080fd5b919050565b60008083601f8401126137bf57600080fd5b5081356001600160401b038111156137d657600080fd5b6020830191508360208260051b85010111156137f157600080fd5b9250929050565b803563ffffffff811681146137a857600080fd5b60006020828403121561381e57600080fd5b612a6b82613791565b6000806040838503121561383a57600080fd5b61384383613791565b915061385160208401613791565b90509250929050565b60008060006060848603121561386f57600080fd5b61387884613791565b925061388660208501613791565b9150604084013590509250925092565b6000806000606084860312156138ab57600080fd5b6138b484613791565b9250602084013580151581146138c957600080fd5b91506138d7604085016137f8565b90509250925092565b600080604083850312156138f357600080fd5b6138fc83613791565b946020939093013593505050565b6000806040838503121561391d57600080fd5b61392683613791565b9150613851602084016137f8565b600080600080600080600080600060c08a8c03121561395257600080fd5b89356001600160401b038082111561396957600080fd5b6139758d838e016137ad565b909b50995060208c013591508082111561398e57600080fd5b61399a8d838e016137ad565b909950975060408c01359150808211156139b357600080fd5b506139c08c828d016137ad565b90965094506139d3905060608b016137f8565b92506139e160808b016137f8565b91506139ef60a08b016137f8565b90509295985092959850929598565b600080600080600060a08688031215613a1657600080fd5b85356001600160801b0381168114613a2d57600080fd5b9450613a3b602087016137f8565b9350613a49604087016137f8565b9250613a57606087016137f8565b9150613a65608087016137f8565b90509295509295909350565b600060208284031215613a8357600080fd5b5035919050565b60008060408385031215613a9d57600080fd5b50508035926020909101359150565b600060208284031215613abe57600080fd5b813569ffffffffffffffffffff81168114612a6b57600080fd5b6020808252825182820181905260009190848201906040850190845b81811015613b195783516001600160a01b031683529284019291840191600101613af4565b50909695505050505050565b600060208083528351808285015260005b81811015613b5257858101830151858201604001528201613b36565b81811115613b64576000604083870101525b50601f01601f1916929092016040019392505050565b600080821280156001600160ff1b0384900385131615613b9c57613b9c613dcf565b600160ff1b8390038412811615613bb557613bb5613dcf565b50500190565b60006001600160801b03808316818516808303821115613bdd57613bdd613dcf565b01949350505050565b60008219821115613bf957613bf9613dcf565b500190565b600063ffffffff808316818516808303821115613bdd57613bdd613dcf565b60006001600160401b03808316818516808303821115613bdd57613bdd613dcf565b600082613c4e57613c4e613de5565b600160ff1b821460001984141615613c6857613c68613dcf565b500590565b600082613c7c57613c7c613de5565b500490565b6000816000190483118215151615613c9b57613c9b613dcf565b500290565b60008083128015600160ff1b850184121615613cbe57613cbe613dcf565b6001600160ff1b0384018313811615613cd957613cd9613dcf565b50500390565b60006001600160801b0383811690831681811015613cff57613cff613dcf565b039392505050565b600082821015613d1957613d19613dcf565b500390565b600063ffffffff83811690831681811015613cff57613cff613dcf565b600181811c90821680613d4f57607f821691505b60208210811415613d7057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613d8a57613d8a613dcf565b5060010190565b600082613da057613da0613de5565b500790565b600082613db457613db4613de5565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fdfea2646970667358221220c726875ffcfc9711c872eda1856d676987501842693719c2ecd3a7f1968df3be64736f6c63430008060033000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008f0d180000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000135052494345204645454420555344542f55534400000000000000000000000000
Deployed ByteCode
0x6080604052600436106102345760003560e01c8063668a0f021161012e578063b5ab58dc116100ab578063d4cc54e41161006f578063d4cc54e4146107f7578063e2e403171461081c578063e9ee6eeb1461085b578063f2fde38b1461087b578063feaf968c1461089b57610243565b8063b5ab58dc14610753578063b633620c14610773578063c107532914610793578063c35905c6146107b3578063c9374500146107d357610243565b80638205bf6a116100f25780638205bf6a146105ec57806388aa80e7146106315780638da5cb5b146106ae57806398e5b12a146106cc5780639a6fc8f5146106fc57610243565b8063668a0f021461053a57806370dea79a1461055d578063715018a6146105815780637284e416146105965780637c2b0b21146105b857610243565b80633d3d7714116101bc57806354fd4d501161018057806354fd4d501461048a57806358609e441461049f578063613d8fcc146104c3578063628806ef146104d857806364efb22b146104f857610243565b80633d3d7714146103cf57806340884c52146103ef57806346fcff4c146104115780634f8fc3b51461044357806350d25bcd1461045857610243565b8063313ce56711610203578063313ce567146102f2578063357ebb021461031e57806338aa4c72146103575780633969c20f146103775780633a5381b51461039757610243565b80631327d3d81461024b578063202ee0ed1461026b57806320ed02751461028b57806323ca2903146102ab57610243565b36610243576102416108b0565b005b6102416108b0565b34801561025757600080fd5b5061024161026636600461380c565b610946565b34801561027757600080fd5b50610241610286366004613a8a565b6109b6565b34801561029757600080fd5b506102416102a6366004613896565b610b08565b3480156102b757600080fd5b506102df7f0000000000000000000000000000000000000000000000000000000008f0d18081565b6040519081526020015b60405180910390f35b3480156102fe57600080fd5b5060035461030c9060ff1681565b60405160ff90911681526020016102e9565b34801561032a57600080fd5b5060025461034290600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102e9565b34801561036357600080fd5b506102416103723660046139fe565b610bfd565b34801561038357600080fd5b50610241610392366004613934565b610f38565b3480156103a357600080fd5b506001546103b7906001600160a01b031681565b6040516001600160a01b0390911681526020016102e9565b3480156103db57600080fd5b506102416103ea36600461385a565b6110e2565b3480156103fb57600080fd5b5061040461123f565b6040516102e99190613ad8565b34801561041d57600080fd5b50600b546001600160801b03165b6040516001600160801b0390911681526020016102e9565b34801561044f57600080fd5b506102416108b0565b34801561046457600080fd5b50600554640100000000900463ffffffff166000908152600760205260409020546102df565b34801561049657600080fd5b506102df600381565b3480156104ab57600080fd5b5060025461034290600160801b900463ffffffff1681565b3480156104cf57600080fd5b50600a5461030c565b3480156104e457600080fd5b506102416104f336600461380c565b6112a1565b34801561050457600080fd5b506103b761051336600461380c565b6001600160a01b039081166000908152600660205260409020600201546201000090041690565b34801561054657600080fd5b50600554640100000000900463ffffffff166102df565b34801561056957600080fd5b5060025461034290600160e01b900463ffffffff1681565b34801561058d57600080fd5b50610241611382565b3480156105a257600080fd5b506105ab611396565b6040516102e99190613b25565b3480156105c457600080fd5b506102df7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f857600080fd5b50600554640100000000900463ffffffff16600090815260076020526040902060010154600160401b90046001600160401b03166102df565b34801561063d57600080fd5b5061065161064c36600461390a565b611424565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102e9565b3480156106ba57600080fd5b506000546001600160a01b03166103b7565b3480156106d857600080fd5b506106e1611581565b60405169ffffffffffffffffffff90911681526020016102e9565b34801561070857600080fd5b5061071c610717366004613aac565b61168c565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102e9565b34801561075f57600080fd5b506102df61076e366004613a71565b611792565b34801561077f57600080fd5b506102df61078e366004613a71565b6117c8565b34801561079f57600080fd5b506102416107ae3660046138e0565b611809565b3480156107bf57600080fd5b5060025461042b906001600160801b031681565b3480156107df57600080fd5b5060025461034290600160a01b900463ffffffff1681565b34801561080357600080fd5b50600b54600160801b90046001600160801b031661042b565b34801561082857600080fd5b506102df61083736600461380c565b6001600160a01b03166000908152600660205260409020546001600160801b031690565b34801561086757600080fd5b50610241610876366004613827565b611899565b34801561088757600080fd5b5061024161089636600461380c565b611975565b3480156108a757600080fd5b5061071c6119ee565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000906108e79047613d07565b82519091506001600160801b0316811461094257600b80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25b5050565b61094e611a28565b6001546001600160a01b03908116908216811461094257600180546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35050565b60006109c23384611a82565b90507f0000000000000000000000000000000000000000000000000000000000000000821215610a395760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000008f0d180821315610aa95760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c756500006044820152606401610a30565b8051819015610acb5760405162461bcd60e51b8152600401610a309190613b25565b50610ad583611d11565b610adf8284611daf565b600080610aeb85611e95565b91509150610af885611ff3565b610b0185612109565b5050505050565b610b10611a28565b6001600160a01b03831660009081526009602052604090205460ff1615158215151415610b3c57505050565b8115610b83576001600160a01b0383166000908152600960205260409020805464ffffffffff191683151564ffffffff0019161761010063ffffffff841602179055610bac565b6001600160a01b0383166000908152600960205260409020805468ffffffffffffffffff191690555b60408051831515815263ffffffff831660208201526001600160a01b038516917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b505050565b610c05611a28565b6000610c10600a5490565b60ff1690508463ffffffff168463ffffffff161015610c715760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e000000000000006044820152606401610a30565b8363ffffffff168163ffffffff161015610ccd5760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401610a30565b63ffffffff81161580610ceb57508263ffffffff168163ffffffff16115b610d375760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401610a30565b610d49866001600160801b0316612166565b600b546001600160801b03161015610da35760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401610a30565b6000610dae600a5490565b60ff161115610e0d5760008563ffffffff1611610e0d5760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401610a30565b85600260006101000a8154816001600160801b0302191690836001600160801b0316021790555084600260146101000a81548163ffffffff021916908363ffffffff16021790555083600260106101000a81548163ffffffff021916908363ffffffff16021790555082600260186101000a81548163ffffffff021916908363ffffffff160217905550816002601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600260009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f8686604051610f2892919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b610f40611a28565b60005b88811015610f8c57610f7a8a8a83818110610f6057610f60613e11565b9050602002016020810190610f75919061380c565b61218a565b80610f8481613d76565b915050610f43565b50858414610fdc5760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e746044820152606401610a30565b604d86610fe8600a5490565b60ff16610ff59190613be6565b11156110395760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b6044820152606401610a30565b60005b868110156110ac5761109a88888381811061105957611059613e11565b905060200201602081019061106e919061380c565b87878481811061108057611080613e11565b9050602002016020810190611095919061380c565b61235c565b806110a481613d76565b91505061103c565b506002546110d7906001600160801b03811690859085908590600160e01b900463ffffffff16610bfd565b505050505050505050565b6001600160a01b0383811660009081526006602052604090206002015462010000900416331461114d5760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610a30565b6001600160a01b03831660009081526006602052604090205481906001600160801b039081169082168110156111c55760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e6473006044820152606401610a30565b6111cf8282613cdf565b6001600160a01b038616600090815260066020526040902080546001600160801b0319166001600160801b03928316179055600b54611217918491600160801b900416613cdf565b600b80546001600160801b03928316600160801b02908316179055610b0190859084166125e1565b6060600a80548060200260200160405190810160405280929190818152602001828054801561129757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611279575b5050505050905090565b6001600160a01b0381811660009081526006602052604090206003015416331461130d5760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e00006044820152606401610a30565b6001600160a01b0381166000818152600660205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b61138a611a28565b6113946000612641565b565b600480546113a390613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546113cf90613d3b565b801561141c5780601f106113f15761010080835404028352916020019161141c565b820191906000526020600020905b8154815290600101906020018083116113ff57829003601f168201915b505050505081565b6000808080808080803332146114755760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b6044820152606401610a30565b63ffffffff89161561155a5763ffffffff8916600090815260076020908152604080832060089092529091206114ab8c8c612691565b6001600160a01b038d1660009081526006602052604090206001908101548482015491840154600b548f936001600160401b03169163ffffffff600160401b90910416906001600160801b0316611501600a5490565b60018901546001600160401b0316611524576002546001600160801b031661153a565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611574565b6115638a6126fb565b975097509750975097509750975097505b9295985092959890939650565b3360009081526009602052604081205460ff166115e05760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a65642072657175657374657200000000000000006044820152606401610a30565b60055463ffffffff16600081815260076020526040902060010154600160401b90046001600160401b031615158061161c575061161c816128c9565b6116685760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c65006044820152606401610a30565b6000611675826001613bfe565b905061168081612948565b63ffffffff1692915050565b63ffffffff80821660009081526007602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611715575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b8152509061175b5760405162461bcd60e51b8152600401610a309190613b25565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006117a28263ffffffff101590565b156117c0575063ffffffff1660009081526007602052604090205490565b506000919050565b60006117d88263ffffffff101590565b156117c0575063ffffffff16600090815260076020526040902060010154600160401b90046001600160401b031690565b611811611a28565b600b546002546001600160801b0391821691839161182f9116612166565b6118399083613d07565b10156118875760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e64730000000000006044820152606401610a30565b61189183836125e1565b610bf86108b0565b6001600160a01b038281166000908152600660205260409020600201546201000090041633146119045760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b6044820152606401610a30565b6001600160a01b0382811660008181526006602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b61197d611a28565b6001600160a01b0381166119e25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a30565b6119eb81612641565b50565b6000806000806000611a17600560049054906101000a900463ffffffff1663ffffffff1661168c565b945094509450945094509091929394565b6000546001600160a01b031633146113945760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a30565b6001600160a01b03821660009081526006602052604090205460055460609163ffffffff600160801b9091048116911681611aeb57604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050611d0b565b8363ffffffff168263ffffffff161115611b3757604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050611d0b565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160a01b909204161015611ba6576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050611d0b565b6001600160a01b03851660009081526006602052604090205463ffffffff808616600160c01b9092041610611c14576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050611d0b565b8063ffffffff168463ffffffff1614158015611c465750611c36816001613bfe565b63ffffffff168463ffffffff1614155b8015611c595750611c578482612a1e565b155b15611c9d576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050611d0b565b8363ffffffff16600114158015611cc45750611cc2611cbd600186613d1e565b612a72565b155b15611d08576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050611d0b565b50505b92915050565b611d1a81612aac565b611d215750565b3360009081526006602052604090205460025463ffffffff600160e01b909204821691611d5691600160c01b90041682613be6565b8263ffffffff1611158015611d6a57508015155b15611d73575050565b611d7c82612ad8565b50336000908152600660205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff80821660009081526008602052604090206001015416611e165760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e73006044820152606401610a30565b63ffffffff8116600081815260086020908152604080832080546001808201835591855283852001879055338085526006909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff80821660009081526008602052604081206001810154905491928392640100000000909204161115611ed157506000928392509050565b63ffffffff831660009081526008602090815260408083208054825181850281018501909352808352611f3793830182828015611f2d57602002820191906000526020600020905b815481526020019060010190808311611f19575b5050505050612c63565b63ffffffff851660008181526007602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556005805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260086020908152604091829020600101548251808401909352600b546001600160801b03808216808652600160801b909204811693850193909352600160601b9091049091169190612052908390613cdf565b6001600160801b03168152602081015161206d908390613bbb565b6001600160801b03908116602083810182905283518316600160801b90920291909117600b55336000908152600690915260409020546120af91849116613bbb565b3360009081526006602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff808216600090815260086020526040902060018101549054911611156121315750565b63ffffffff81166000908152600860205260408120906121518282613713565b5060010180546001600160e01b031916905550565b60006002612173600a5490565b6121809060ff1684613c81565b611d0b9190613c81565b61219381612d23565b6121d45760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b6044820152606401610a30565b6005546121e89063ffffffff166001613bfe565b6001600160a01b0382166000908152600660205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600a6001612231600a5490565b60ff1661223e9190613d07565b8154811061224e5761224e613e11565b6000918252602080832091909101546001600160a01b0385811680855260069093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600a80549293509091839190839081106122c0576122c0613e11565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a8054806122ff576122ff613dfb565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61236582612d23565b156123ab5760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b6044820152606401610a30565b6001600160a01b0381166123f95760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b6044820152606401610a30565b6001600160a01b0382811660009081526006602052604090206002015462010000900416158061244e57506001600160a01b038281166000908152600660205260409020600201546201000090048116908216145b61249a5760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e000000006044820152606401610a30565b6124a382612d4e565b6001600160a01b03838116600081815260066020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600a80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461262e576040519150601f19603f3d011682016040523d82523d6000602084013e612633565b606091505b5050905080610bf857600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b63ffffffff81166000908152600760205260408120600101546001600160401b0316156126f15763ffffffff8083166000908152600860205260409020600101541615155b80156126ea57506126e78383611a82565b51155b9050611d0b565b6126d68383612da6565b6001600160a01b0381166000908152600660205260408120600554815483928392839283928392839283927f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df929091849163ffffffff908116600160c01b909204161480612784575060055463ffffffff90811660009081526008602052604090206001015416155b6005549091506127999063ffffffff16612a72565b80156127a25750805b156127f6576005546127bb9063ffffffff166001613bfe565b63ffffffff81166000908152600760205260409020600254919b506001600160801b03909116945092506127ef8c8b612da6565b9a5061283b565b60055463ffffffff9081166000818152600760209081526040808320600890925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b6128458c8b611a82565b51156128505760009a505b6001808301548482015463ffffffff808e16600090815260086020526040902090930154600b548f948f94936001600160401b031692600160401b900416906001600160801b03166128a1600a5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526007602090815260408083206001908101546008909352908320015491926001600160401b0390911691600160401b900416811580159061291d575060008163ffffffff16115b801561294057504261293563ffffffff831684613c1d565b6001600160401b0316105b949350505050565b61295181612aac565b6129585750565b3360009081526009602052604090205463ffffffff65010000000000820481169161298a916101009091041682613be6565b8263ffffffff16118061299b575080155b6129dd5760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b6044820152606401610a30565b6129e682612ad8565b50336000908152600960205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b600063ffffffff8216612a32846001613bfe565b63ffffffff16148015612a6b575063ffffffff8216600090815260076020526040902060010154600160401b90046001600160401b0316155b9392505050565b63ffffffff8116600090815260076020526040812060010154600160401b90046001600160401b0316151580611d0b5750611d0b826128c9565b600554600090612ac39063ffffffff166001613bfe565b63ffffffff168263ffffffff16149050919050565b612aeb612ae6600183613d1e565b612dfa565b6005805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600254600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526008845291208151805192938493612b769284920190613731565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526007845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b60008151600010612caf5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b6044820152606401610a30565b81516000612cbe600283613c6d565b9050612ccb600283613da5565b612d0c57600080612cf38682612ce2600188613d07565b612ced600188613d07565b87612ebd565b9092509050612d028282612fb5565b9695505050505050565b612940846000612d1d600186613d07565b8461304d565b6001600160a01b0316600090815260066020526040902054600160a01b900463ffffffff9081161490565b60055460009063ffffffff168015801590612d9057506001600160a01b03831660009081526006602052604090205463ffffffff828116600160a01b90920416145b15612d9b5792915050565b612a6b816001613bfe565b6001600160a01b03821660009081526006602052604081205460025463ffffffff600160e01b909204821691612de491600160c01b90041682613be6565b8363ffffffff1611806129405750159392505050565b612e03816128c9565b612e0a5750565b6000612e17600183613d1e565b63ffffffff818116600090815260076020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b0316021790935560089052908120919250612ea78282613713565b5060010180546001600160e01b03191690555050565b600080828410612ecc57600080fd5b838611158015612edc5750848411155b612ee557600080fd5b828611158015612ef55750848311155b612efe57600080fd5b6007612f0a8787613d07565b1015612f2657612f1d87878787876130f2565b91509150612fab565b6000612f3388888861353c565b9050808411612f4457809550612fa5565b84811015612f5e57612f57816001613be6565b9650612fa5565b808511158015612f6d57508381105b612f7957612f79613db9565b612f858888838861304d565b9250612f9d88612f96836001613be6565b888761304d565b915050612fab565b50612efe565b9550959350505050565b60008083128015612fc65750600082135b80612fdc5750600083138015612fdc5750600082125b15612ff7576002612fed848461366c565b6126ea9190613c3f565b600060026130058185613d91565b613010600287613d91565b61301a9190613b7a565b6130249190613c3f565b9050612940613047613037600287613c3f565b613042600287613c3f565b61366c565b8261366c565b60008184111561305c57600080fd5b8282111561306957600080fd5b828410156130ce57600761307d8585613d07565b101561309c57600061309286868686876130f2565b5091506129409050565b60006130a986868661353c565b90508083116130ba578093506130c8565b6130c5816001613be6565b94505b50613069565b8484815181106130e0576130e0613e11565b60200260200101519050949350505050565b6000808086613102876001613be6565b61310c9190613d07565b905060008861311b8983613be6565b8151811061312b5761312b613e11565b6020026020010151905060008260011061314c576001600160ff1b03613171565b896131588a6001613be6565b8151811061316857613168613e11565b60200260200101515b905060008360021061318a576001600160ff1b036131af565b8a6131968b6002613be6565b815181106131a6576131a6613e11565b60200260200101515b90506000846003106131c8576001600160ff1b036131ed565b8b6131d48c6003613be6565b815181106131e4576131e4613e11565b60200260200101515b9050600085600410613206576001600160ff1b0361322b565b8c6132128d6004613be6565b8151811061322257613222613e11565b60200260200101515b9050600086600510613244576001600160ff1b03613269565b8d6132508e6005613be6565b8151811061326057613260613e11565b60200260200101515b9050600087600610613282576001600160ff1b036132a7565b8e61328e8f6006613be6565b8151811061329e5761329e613e11565b60200260200101515b9050858713156132b5579495945b838513156132c1579293925b818313156132cd579091905b848713156132d9579395935b838613156132e5579294925b808313156132ef57915b848613156132fb579394935b8082131561330557905b82871315613311579195915b8186131561331d579094905b8085131561332757935b82861315613333579194915b8084131561333d57925b82851315613349579193915b81841315613355579092905b82841315613361579192915b600061336d8f8e613d07565b90508061337c57879a5061341d565b806001141561338d57869a5061341d565b806002141561339e57859a5061341d565b80600314156133af57849a5061341d565b80600414156133c057839a5061341d565b80600514156133d157829a5061341d565b80600614156133e257819a5061341d565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b6044820152606401610a30565b60008f8d61342b9190613d07565b90508c8e141561344857508a9950612fab98505050505050505050565b8061345f5750969850612fab975050505050505050565b806001141561347a5750959850612fab975050505050505050565b80600214156134955750949850612fab975050505050505050565b80600314156134b05750939850612fab975050505050505050565b80600414156134cb5750929850612fab975050505050505050565b80600514156134e65750919850612fab975050505050505050565b80600614156135015750909850612fab975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b6044820152606401610a30565b60008084600261354c8587613be6565b6135569190613c6d565b8151811061356657613566613e11565b6020026020010151905060018461357d9190613d07565b935061358a600184613be6565b92505b613598600185613be6565b9350808585815181106135ad576135ad613e11565b60200260200101511261358d575b6135c6600184613d07565b9250808584815181106135db576135db613e11565b6020026020010151136135bb57828410156136635784838151811061360257613602613e11565b602002602001015185858151811061361c5761361c613e11565b602002602001015186868151811061363657613636613e11565b6020026020010187868151811061364f5761364f613e11565b60209081029190910101919091525261358d565b50909392505050565b600080821215801561368e575061368a826001600160ff1b03613ca0565b8313155b806136b157506000821280156136b157506136ad82600160ff1b613ca0565b8312155b6137075760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b6064820152608401610a30565b60006129408385613b7a565b50805460008255906000526020600020908101906119eb919061377c565b82805482825590600052602060002090810192821561376c579160200282015b8281111561376c578251825591602001919060010190613751565b5061377892915061377c565b5090565b5b80821115613778576000815560010161377d565b80356001600160a01b03811681146137a857600080fd5b919050565b60008083601f8401126137bf57600080fd5b5081356001600160401b038111156137d657600080fd5b6020830191508360208260051b85010111156137f157600080fd5b9250929050565b803563ffffffff811681146137a857600080fd5b60006020828403121561381e57600080fd5b612a6b82613791565b6000806040838503121561383a57600080fd5b61384383613791565b915061385160208401613791565b90509250929050565b60008060006060848603121561386f57600080fd5b61387884613791565b925061388660208501613791565b9150604084013590509250925092565b6000806000606084860312156138ab57600080fd5b6138b484613791565b9250602084013580151581146138c957600080fd5b91506138d7604085016137f8565b90509250925092565b600080604083850312156138f357600080fd5b6138fc83613791565b946020939093013593505050565b6000806040838503121561391d57600080fd5b61392683613791565b9150613851602084016137f8565b600080600080600080600080600060c08a8c03121561395257600080fd5b89356001600160401b038082111561396957600080fd5b6139758d838e016137ad565b909b50995060208c013591508082111561398e57600080fd5b61399a8d838e016137ad565b909950975060408c01359150808211156139b357600080fd5b506139c08c828d016137ad565b90965094506139d3905060608b016137f8565b92506139e160808b016137f8565b91506139ef60a08b016137f8565b90509295985092959850929598565b600080600080600060a08688031215613a1657600080fd5b85356001600160801b0381168114613a2d57600080fd5b9450613a3b602087016137f8565b9350613a49604087016137f8565b9250613a57606087016137f8565b9150613a65608087016137f8565b90509295509295909350565b600060208284031215613a8357600080fd5b5035919050565b60008060408385031215613a9d57600080fd5b50508035926020909101359150565b600060208284031215613abe57600080fd5b813569ffffffffffffffffffff81168114612a6b57600080fd5b6020808252825182820181905260009190848201906040850190845b81811015613b195783516001600160a01b031683529284019291840191600101613af4565b50909695505050505050565b600060208083528351808285015260005b81811015613b5257858101830151858201604001528201613b36565b81811115613b64576000604083870101525b50601f01601f1916929092016040019392505050565b600080821280156001600160ff1b0384900385131615613b9c57613b9c613dcf565b600160ff1b8390038412811615613bb557613bb5613dcf565b50500190565b60006001600160801b03808316818516808303821115613bdd57613bdd613dcf565b01949350505050565b60008219821115613bf957613bf9613dcf565b500190565b600063ffffffff808316818516808303821115613bdd57613bdd613dcf565b60006001600160401b03808316818516808303821115613bdd57613bdd613dcf565b600082613c4e57613c4e613de5565b600160ff1b821460001984141615613c6857613c68613dcf565b500590565b600082613c7c57613c7c613de5565b500490565b6000816000190483118215151615613c9b57613c9b613dcf565b500290565b60008083128015600160ff1b850184121615613cbe57613cbe613dcf565b6001600160ff1b0384018313811615613cd957613cd9613dcf565b50500390565b60006001600160801b0383811690831681811015613cff57613cff613dcf565b039392505050565b600082821015613d1957613d19613dcf565b500390565b600063ffffffff83811690831681811015613cff57613cff613dcf565b600181811c90821680613d4f57607f821691505b60208210811415613d7057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613d8a57613d8a613dcf565b5060010190565b600082613da057613da0613de5565b500790565b600082613db457613db4613de5565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fdfea2646970667358221220c726875ffcfc9711c872eda1856d676987501842693719c2ecd3a7f1968df3be64736f6c63430008060033