Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- FluxAggregator
- Optimization enabled
- true
- Compiler version
- v0.8.6+commit.11564f7e
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-07-10T08:18:04.388450Z
Constructor Arguments
0x0000000000000000000000004084ab20f8ffca76c19aaf854fb5fe9de6217fbb00000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000055052494345000000000000000000000000000000000000000000000000000000
Arg [0] (address) : 0x4084ab20f8ffca76c19aaf854fb5fe9de6217fbb
Arg [1] (uint128) : 1000000000000000
Arg [2] (uint32) : 1000
Arg [3] (int256) : 0
Arg [4] (int256) : 1000
Arg [5] (uint8) : 18
Arg [6] (string) : PRICE
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 {IWFTN} from "./interfaces/IWFTN.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; } IWFTN public wFTN; 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 _wFTN The address of the wFTN token * @param _paymentAmount The amount paid of wFTN 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( address payable _wFTN, uint128 _paymentAmount, uint32 _timeout, // address _validator, int256 _minSubmissionValue, int256 _maxSubmissionValue, uint8 _decimals, string memory _description ) { wFTN = IWFTN(_wFTN); 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); // } } /** * @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 = wFTN.balanceOf(address(this)) - (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 transfers the oracle's wFTN to another address. Can only be called * by the oracle's admin. * @param _oracle is the oracle whose wFTN is transferred * @param _recipient is the address to send the wFTN to * @param _amount is the amount of wFTN 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); assert(wFTN.transfer(_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"); require(wFTN.transfer(_recipient, _amount), "token transfer failed"); 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/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); } }
@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; } }
@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); } }
contracts/interfaces/AggregatorInterface.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; interface AggregatorInterface { function latestAnswer() external view returns ( int256 ); function latestTimestamp() external view returns ( uint256 ); function latestRound() external view returns ( uint256 ); function getAnswer( uint256 roundId ) external view returns ( int256 ); function getTimestamp( uint256 roundId ) external view returns ( uint256 ); event AnswerUpdated( int256 indexed current, uint256 indexed roundId, uint256 updatedAt ); event NewRound( uint256 indexed roundId, address indexed startedBy, uint256 startedAt ); }
contracts/interfaces/AggregatorV2V3Interface.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; import "./AggregatorInterface.sol"; import "./AggregatorV3Interface.sol"; interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface { }
contracts/interfaces/AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; interface AggregatorV3Interface { function decimals() external view returns ( uint8 ); function description() external view returns ( string memory ); function version() external view returns ( uint256 ); function getRoundData( uint80 _roundId ) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
contracts/interfaces/AggregatorValidatorInterface.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; interface AggregatorValidatorInterface { function validate( uint256 previousRoundId, int256 previousAnswer, uint256 currentRoundId, int256 currentAnswer ) external returns (bool); }
contracts/interfaces/IWFTN.sol
// SPDX-License-Identifier: MIT // Copyright (C) 2024 Fasttoken // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.6; interface IWFTN { receive() external payable; function deposit() external payable; function withdraw(uint256 amount_) external; function balanceOf(address account) external view returns (uint256); function totalSupply() external view returns (uint256); function approve(address to_, uint256 amount_) external returns (bool); function transfer(address to_, uint256 amount_) external returns (bool); function transferFrom(address src_, address to_, uint256 amount_) external returns (bool); }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_wFTN","internalType":"address payable"},{"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":"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":"view","outputs":[{"type":"address","name":"","internalType":"contract IWFTN"}],"name":"wFTN","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"}]}]
Contract Creation Code
0x60c06040523480156200001157600080fd5b5060405162004674380380620046748339810160408190526200003491620006c9565b6200003f3362000111565b600180546001600160a01b0319166001600160a01b0389161790556200006a86600080808962000161565b608084905260a08390526004805460ff191660ff841617905580516200009890600590602084019062000540565b50620000ab63ffffffff861642620007a5565b6000805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c880546001600160401b03929092166801000000000000000002600160401b600160801b0319909216919091179055506200082895505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6200016b620004b3565b600062000177600b5490565b60ff1690508463ffffffff168463ffffffff161015620001de5760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064015b60405180910390fd5b8363ffffffff168163ffffffff1610156200023c5760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c0000000000000000006044820152606401620001d5565b63ffffffff811615806200025b57508263ffffffff168163ffffffff16115b620002a95760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c000000000000006044820152606401620001d5565b620002bd6001600160801b03871662000511565b600c546001600160801b03161015620003195760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e7400006044820152606401620001d5565b600062000325600b5490565b60ff161115620003875760008563ffffffff1611620003875760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e20300000000000006044820152606401620001d5565b85600360006101000a8154816001600160801b0302191690836001600160801b0316021790555084600360146101000a81548163ffffffff021916908363ffffffff16021790555083600360106101000a81548163ffffffff021916908363ffffffff16021790555082600360186101000a81548163ffffffff021916908363ffffffff160217905550816003601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600360009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f8686604051620004a392919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b6000546001600160a01b031633146200050f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620001d5565b565b600060026200051f600b5490565b6200052e9060ff168462000783565b6200053a919062000783565b92915050565b8280546200054e90620007bf565b90600052602060002090601f016020900481019282620005725760008555620005bd565b82601f106200058d57805160ff1916838001178555620005bd565b82800160010185558215620005bd579182015b82811115620005bd578251825591602001919060010190620005a0565b50620005cb929150620005cf565b5090565b5b80821115620005cb5760008155600101620005d0565b600082601f830112620005f857600080fd5b81516001600160401b038082111562000615576200061562000812565b604051601f8301601f19908116603f0116810190828211818310171562000640576200064062000812565b816040528381526020925086838588010111156200065d57600080fd5b600091505b8382101562000681578582018301518183018401529082019062000662565b83821115620006935760008385830101525b9695505050505050565b805163ffffffff81168114620006b257600080fd5b919050565b805160ff81168114620006b257600080fd5b600080600080600080600060e0888a031215620006e557600080fd5b87516001600160a01b0381168114620006fd57600080fd5b60208901519097506001600160801b03811681146200071b57600080fd5b95506200072b604089016200069d565b945060608801519350608088015192506200074960a08901620006b7565b60c08901519092506001600160401b038111156200076657600080fd5b620007748a828b01620005e6565b91505092959891949750929550565b6000816000190483118215151615620007a057620007a0620007fc565b500290565b600082821015620007ba57620007ba620007fc565b500390565b600181811c90821680620007d457607f821691505b60208210811415620007f657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160a051613e186200085c6000396000818161028d01526107c2015260008181610496015261074d0152613e186000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806370dea79a1161013b578063b633620c116100b8578063d4cc54e41161007c578063d4cc54e414610654578063e2e403171461066c578063e9ee6eeb1461069e578063f2fde38b146106b1578063feaf968c146106c457600080fd5b8063b633620c146105f1578063b7e2a68a14610604578063c107532914610617578063c35905c61461062a578063c93745001461063d57600080fd5b806388aa80e7116100ff57806388aa80e7146104f05780638da5cb5b1461056057806398e5b12a146105715780639a6fc8f514610594578063b5ab58dc146105de57600080fd5b806370dea79a1461045d578063715018a6146104745780637284e4161461047c5780637c2b0b21146104915780638205bf6a146104b857600080fd5b806340884c52116101c957806358609e441161018d57806358609e44146103e0578063613d8fcc146103f7578063628806ef146103ff57806364efb22b14610412578063668a0f021461044757600080fd5b806340884c521461037157806346fcff4c146103865780634f8fc3b5146103ab57806350d25bcd146103b357806354fd4d50146103d857600080fd5b8063357ebb0211610210578063357ebb02146102e157806338aa4c721461030d5780633969c20f146103205780633a5381b5146103335780633d3d77141461035e57600080fd5b80631327d3d81461024d578063202ee0ed1461026257806320ed02751461027557806323ca290314610288578063313ce567146102c2575b600080fd5b61026061025b366004613788565b6106cc565b005b610260610270366004613a37565b61073d565b610260610283366004613812565b61088f565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6004546102cf9060ff1681565b60405160ff90911681526020016102b9565b6003546102f890600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102b9565b61026061031b366004613992565b610984565b61026061032e3660046138ab565b610cbf565b600254610346906001600160a01b031681565b6040516001600160a01b0390911681526020016102b9565b61026061036c3660046137d6565b610e69565b61037961104b565b6040516102b99190613a85565b600c546001600160801b03165b6040516001600160801b0390911681526020016102b9565b6102606110ad565b600654640100000000900463ffffffff166000908152600860205260409020546102af565b6102af600381565b6003546102f890600160801b900463ffffffff1681565b600b546102cf565b61026061040d366004613788565b6111bd565b610346610420366004613788565b6001600160a01b039081166000908152600760205260409020600201546201000090041690565b600654640100000000900463ffffffff166102af565b6003546102f890600160e01b900463ffffffff1681565b61026061129e565b6104846112b2565b6040516102b99190613ad2565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b600654640100000000900463ffffffff16600090815260086020526040902060010154600160401b90046001600160401b03166102af565b6105036104fe366004613881565b611340565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102b9565b6000546001600160a01b0316610346565b61057961149d565b60405169ffffffffffffffffffff90911681526020016102b9565b6105a76105a2366004613a59565b6115a8565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102b9565b6102af6105ec366004613a05565b6116ae565b6102af6105ff366004613a05565b6116e4565b600154610346906001600160a01b031681565b610260610625366004613857565b611725565b600354610393906001600160801b031681565b6003546102f890600160a01b900463ffffffff1681565b600c54600160801b90046001600160801b0316610393565b6102af61067a366004613788565b6001600160a01b03166000908152600760205260409020546001600160801b031690565b6102606106ac3660046137a3565b611875565b6102606106bf366004613788565b611951565b6105a76119ca565b6106d4611a04565b6002546001600160a01b03908116908216811461073957600280546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b5050565b60006107493384611a5e565b90507f00000000000000000000000000000000000000000000000000000000000000008212156107c05760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008213156108305760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c7565000060448201526064016107b7565b80518190156108525760405162461bcd60e51b81526004016107b79190613ad2565b5061085c83611ced565b6108668284611d8b565b60008061087285611e71565b9150915061087f85611fcf565b610888856120e5565b5050505050565b610897611a04565b6001600160a01b0383166000908152600a602052604090205460ff16151582151514156108c357505050565b811561090a576001600160a01b0383166000908152600a60205260409020805464ffffffffff191683151564ffffffff0019161761010063ffffffff841602179055610933565b6001600160a01b0383166000908152600a60205260409020805468ffffffffffffffffff191690555b60408051831515815263ffffffff831660208201526001600160a01b038516917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b505050565b61098c611a04565b6000610997600b5490565b60ff1690508463ffffffff168463ffffffff1610156109f85760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064016107b7565b8363ffffffff168163ffffffff161015610a545760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c00000000000000000060448201526064016107b7565b63ffffffff81161580610a7257508263ffffffff168163ffffffff16115b610abe5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c0000000000000060448201526064016107b7565b610ad0866001600160801b0316612142565b600c546001600160801b03161015610b2a5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e74000060448201526064016107b7565b6000610b35600b5490565b60ff161115610b945760008563ffffffff1611610b945760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e203000000000000060448201526064016107b7565b85600360006101000a8154816001600160801b0302191690836001600160801b0316021790555084600360146101000a81548163ffffffff021916908363ffffffff16021790555083600360106101000a81548163ffffffff021916908363ffffffff16021790555082600360186101000a81548163ffffffff021916908363ffffffff160217905550816003601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600360009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f8686604051610caf92919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b610cc7611a04565b60005b88811015610d1357610d018a8a83818110610ce757610ce7613dbe565b9050602002016020810190610cfc9190613788565b612166565b80610d0b81613d23565b915050610cca565b50858414610d635760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e7460448201526064016107b7565b604d86610d6f600b5490565b60ff16610d7c9190613b93565b1115610dc05760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b60448201526064016107b7565b60005b86811015610e3357610e21888883818110610de057610de0613dbe565b9050602002016020810190610df59190613788565b878784818110610e0757610e07613dbe565b9050602002016020810190610e1c9190613788565b612338565b80610e2b81613d23565b915050610dc3565b50600354610e5e906001600160801b03811690859085908590600160e01b900463ffffffff16610984565b505050505050505050565b6001600160a01b03838116600090815260076020526040902060020154620100009004163314610ed45760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b60448201526064016107b7565b6001600160a01b03831660009081526007602052604090205481906001600160801b03908116908216811015610f4c5760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e64730060448201526064016107b7565b610f568282613c8c565b6001600160a01b038616600090815260076020526040902080546001600160801b0319166001600160801b03928316179055600c54610f9e918491600160801b900416613c8c565b600c80546001600160801b03928316600160801b0290831617905560015460405163a9059cbb60e01b81526001600160a01b038781166004830152928516602482015291169063a9059cbb90604401602060405180830381600087803b15801561100757600080fd5b505af115801561101b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103f9190613975565b61088857610888613d66565b6060600b8054806020026020016040519081016040528092919081815260200182805480156110a357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611085575b5050505050905090565b604080518082018252600c546001600160801b038082168352600160801b909104166020820181905260015492516370a0823160e01b815230600482015291926000926001600160a01b03909116906370a082319060240160206040518083038186803b15801561111d57600080fd5b505afa158015611131573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111559190613a1e565b61115f9190613cb4565b82519091506001600160801b0316811461073957600c80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25050565b6001600160a01b038181166000908152600760205260409020600301541633146112295760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e000060448201526064016107b7565b6001600160a01b0381166000818152600760205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b6112a6611a04565b6112b060006125bd565b565b600580546112bf90613ce8565b80601f01602080910402602001604051908101604052809291908181526020018280546112eb90613ce8565b80156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b505050505081565b6000808080808080803332146113915760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b60448201526064016107b7565b63ffffffff8916156114765763ffffffff8916600090815260086020908152604080832060099092529091206113c78c8c61260d565b6001600160a01b038d1660009081526007602052604090206001908101548482015491840154600c548f936001600160401b03169163ffffffff600160401b90910416906001600160801b031661141d600b5490565b60018901546001600160401b0316611440576003546001600160801b0316611456565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611490565b61147f8a612677565b975097509750975097509750975097505b9295985092959890939650565b336000908152600a602052604081205460ff166114fc5760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a656420726571756573746572000000000000000060448201526064016107b7565b60065463ffffffff16600081815260086020526040902060010154600160401b90046001600160401b0316151580611538575061153881612845565b6115845760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c650060448201526064016107b7565b6000611591826001613bab565b905061159c816128c4565b63ffffffff1692915050565b63ffffffff80821660009081526008602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611631575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b815250906116775760405162461bcd60e51b81526004016107b79190613ad2565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006116be8263ffffffff101590565b156116dc575063ffffffff1660009081526008602052604090205490565b506000919050565b60006116f48263ffffffff101590565b156116dc575063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031690565b61172d611a04565b600c546003546001600160801b0391821691839161174b9116612142565b6117559083613cb4565b10156117a35760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e647300000000000060448201526064016107b7565b60015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb90604401602060405180830381600087803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118299190613975565b61186d5760405162461bcd60e51b81526020600482015260156024820152741d1bdad95b881d1c985b9cd9995c8819985a5b1959605a1b60448201526064016107b7565b61097f6110ad565b6001600160a01b038281166000908152600760205260409020600201546201000090041633146118e05760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b60448201526064016107b7565b6001600160a01b0382811660008181526007602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b611959611a04565b6001600160a01b0381166119be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107b7565b6119c7816125bd565b50565b60008060008060006119f3600660049054906101000a900463ffffffff1663ffffffff166115a8565b945094509450945094509091929394565b6000546001600160a01b031633146112b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107b7565b6001600160a01b03821660009081526007602052604090205460065460609163ffffffff600160801b9091048116911681611ac757604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050611ce7565b8363ffffffff168263ffffffff161115611b1357604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050611ce7565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160a01b909204161015611b82576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050611ce7565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160c01b9092041610611bf0576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050611ce7565b8063ffffffff168463ffffffff1614158015611c225750611c12816001613bab565b63ffffffff168463ffffffff1614155b8015611c355750611c33848261299a565b155b15611c79576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050611ce7565b8363ffffffff16600114158015611ca05750611c9e611c99600186613ccb565b6129ee565b155b15611ce4576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050611ce7565b50505b92915050565b611cf681612a28565b611cfd5750565b3360009081526007602052604090205460035463ffffffff600160e01b909204821691611d3291600160c01b90041682613b93565b8263ffffffff1611158015611d4657508015155b15611d4f575050565b611d5882612a54565b50336000908152600760205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff80821660009081526009602052604090206001015416611df25760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e730060448201526064016107b7565b63ffffffff8116600081815260096020908152604080832080546001808201835591855283852001879055338085526007909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff80821660009081526009602052604081206001810154905491928392640100000000909204161115611ead57506000928392509050565b63ffffffff831660009081526009602090815260408083208054825181850281018501909352808352611f1393830182828015611f0957602002820191906000526020600020905b815481526020019060010190808311611ef5575b5050505050612bdf565b63ffffffff851660008181526008602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556006805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260096020908152604091829020600101548251808401909352600c546001600160801b03808216808652600160801b909204811693850193909352600160601b909104909116919061202e908390613c8c565b6001600160801b031681526020810151612049908390613b68565b6001600160801b03908116602083810182905283518316600160801b90920291909117600c553360009081526007909152604090205461208b91849116613b68565b3360009081526007602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff8082166000908152600960205260409020600181015490549116111561210d5750565b63ffffffff811660009081526009602052604081209061212d828261368f565b5060010180546001600160e01b031916905550565b6000600261214f600b5490565b61215c9060ff1684613c2e565b611ce79190613c2e565b61216f81612c9f565b6121b05760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b60448201526064016107b7565b6006546121c49063ffffffff166001613bab565b6001600160a01b0382166000908152600760205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600b600161220d600b5490565b60ff1661221a9190613cb4565b8154811061222a5761222a613dbe565b6000918252602080832091909101546001600160a01b0385811680855260079093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600b805492935090918391908390811061229c5761229c613dbe565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b8054806122db576122db613da8565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61234182612c9f565b156123875760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b60448201526064016107b7565b6001600160a01b0381166123d55760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b60448201526064016107b7565b6001600160a01b0382811660009081526007602052604090206002015462010000900416158061242a57506001600160a01b038281166000908152600760205260409020600201546201000090048116908216145b6124765760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e0000000060448201526064016107b7565b61247f82612cca565b6001600160a01b03838116600081815260076020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600b80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b63ffffffff81166000908152600860205260408120600101546001600160401b03161561266d5763ffffffff8083166000908152600960205260409020600101541615155b801561266657506126638383611a5e565b51155b9050611ce7565b6126528383612d22565b6001600160a01b0381166000908152600760205260408120600654815483928392839283928392839283927f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7929091849163ffffffff908116600160c01b909204161480612700575060065463ffffffff90811660009081526009602052604090206001015416155b6006549091506127159063ffffffff166129ee565b801561271e5750805b15612772576006546127379063ffffffff166001613bab565b63ffffffff81166000908152600860205260409020600354919b506001600160801b039091169450925061276b8c8b612d22565b9a506127b7565b60065463ffffffff9081166000818152600860209081526040808320600990925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b6127c18c8b611a5e565b51156127cc5760009a505b6001808301548482015463ffffffff808e16600090815260096020526040902090930154600c548f948f94936001600160401b031692600160401b900416906001600160801b031661281d600b5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526008602090815260408083206001908101546009909352908320015491926001600160401b0390911691600160401b9004168115801590612899575060008163ffffffff16115b80156128bc5750426128b163ffffffff831684613bca565b6001600160401b0316105b949350505050565b6128cd81612a28565b6128d45750565b336000908152600a602052604090205463ffffffff650100000000008204811691612906916101009091041682613b93565b8263ffffffff161180612917575080155b6129595760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b60448201526064016107b7565b61296282612a54565b50336000908152600a60205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b600063ffffffff82166129ae846001613bab565b63ffffffff161480156129e7575063ffffffff8216600090815260086020526040902060010154600160401b90046001600160401b0316155b9392505050565b63ffffffff8116600090815260086020526040812060010154600160401b90046001600160401b0316151580611ce75750611ce782612845565b600654600090612a3f9063ffffffff166001613bab565b63ffffffff168263ffffffff16149050919050565b612a67612a62600183613ccb565b612d76565b6006805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600354600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526009845291208151805192938493612af292849201906136ad565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526008845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b60008151600010612c2b5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b60448201526064016107b7565b81516000612c3a600283613c1a565b9050612c47600283613d52565b612c8857600080612c6f8682612c5e600188613cb4565b612c69600188613cb4565b87612e39565b9092509050612c7e8282612f31565b9695505050505050565b6128bc846000612c99600186613cb4565b84612fc9565b6001600160a01b0316600090815260076020526040902054600160a01b900463ffffffff9081161490565b60065460009063ffffffff168015801590612d0c57506001600160a01b03831660009081526007602052604090205463ffffffff828116600160a01b90920416145b15612d175792915050565b6129e7816001613bab565b6001600160a01b03821660009081526007602052604081205460035463ffffffff600160e01b909204821691612d6091600160c01b90041682613b93565b8363ffffffff1611806128bc5750159392505050565b612d7f81612845565b612d865750565b6000612d93600183613ccb565b63ffffffff818116600090815260086020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b0316021790935560099052908120919250612e23828261368f565b5060010180546001600160e01b03191690555050565b600080828410612e4857600080fd5b838611158015612e585750848411155b612e6157600080fd5b828611158015612e715750848311155b612e7a57600080fd5b6007612e868787613cb4565b1015612ea257612e99878787878761306e565b91509150612f27565b6000612eaf8888886134b8565b9050808411612ec057809550612f21565b84811015612eda57612ed3816001613b93565b9650612f21565b808511158015612ee957508381105b612ef557612ef5613d66565b612f0188888388612fc9565b9250612f1988612f12836001613b93565b8887612fc9565b915050612f27565b50612e7a565b9550959350505050565b60008083128015612f425750600082135b80612f585750600083138015612f585750600082125b15612f73576002612f6984846135e8565b6126669190613bec565b60006002612f818185613d3e565b612f8c600287613d3e565b612f969190613b27565b612fa09190613bec565b90506128bc612fc3612fb3600287613bec565b612fbe600287613bec565b6135e8565b826135e8565b600081841115612fd857600080fd5b82821115612fe557600080fd5b8284101561304a576007612ff98585613cb4565b101561301857600061300e868686868761306e565b5091506128bc9050565b60006130258686866134b8565b905080831161303657809350613044565b613041816001613b93565b94505b50612fe5565b84848151811061305c5761305c613dbe565b60200260200101519050949350505050565b600080808661307e876001613b93565b6130889190613cb4565b90506000886130978983613b93565b815181106130a7576130a7613dbe565b602002602001015190506000826001106130c8576001600160ff1b036130ed565b896130d48a6001613b93565b815181106130e4576130e4613dbe565b60200260200101515b9050600083600210613106576001600160ff1b0361312b565b8a6131128b6002613b93565b8151811061312257613122613dbe565b60200260200101515b9050600084600310613144576001600160ff1b03613169565b8b6131508c6003613b93565b8151811061316057613160613dbe565b60200260200101515b9050600085600410613182576001600160ff1b036131a7565b8c61318e8d6004613b93565b8151811061319e5761319e613dbe565b60200260200101515b90506000866005106131c0576001600160ff1b036131e5565b8d6131cc8e6005613b93565b815181106131dc576131dc613dbe565b60200260200101515b90506000876006106131fe576001600160ff1b03613223565b8e61320a8f6006613b93565b8151811061321a5761321a613dbe565b60200260200101515b905085871315613231579495945b8385131561323d579293925b81831315613249579091905b84871315613255579395935b83861315613261579294925b8083131561326b57915b84861315613277579394935b8082131561328157905b8287131561328d579195915b81861315613299579094905b808513156132a357935b828613156132af579194915b808413156132b957925b828513156132c5579193915b818413156132d1579092905b828413156132dd579192915b60006132e98f8e613cb4565b9050806132f857879a50613399565b806001141561330957869a50613399565b806002141561331a57859a50613399565b806003141561332b57849a50613399565b806004141561333c57839a50613399565b806005141561334d57829a50613399565b806006141561335e57819a50613399565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b60448201526064016107b7565b60008f8d6133a79190613cb4565b90508c8e14156133c457508a9950612f2798505050505050505050565b806133db5750969850612f27975050505050505050565b80600114156133f65750959850612f27975050505050505050565b80600214156134115750949850612f27975050505050505050565b806003141561342c5750939850612f27975050505050505050565b80600414156134475750929850612f27975050505050505050565b80600514156134625750919850612f27975050505050505050565b806006141561347d5750909850612f27975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b60448201526064016107b7565b6000808460026134c88587613b93565b6134d29190613c1a565b815181106134e2576134e2613dbe565b602002602001015190506001846134f99190613cb4565b9350613506600184613b93565b92505b613514600185613b93565b93508085858151811061352957613529613dbe565b602002602001015112613509575b613542600184613cb4565b92508085848151811061355757613557613dbe565b60200260200101511361353757828410156135df5784838151811061357e5761357e613dbe565b602002602001015185858151811061359857613598613dbe565b60200260200101518686815181106135b2576135b2613dbe565b602002602001018786815181106135cb576135cb613dbe565b602090810291909101019190915252613509565b50909392505050565b600080821215801561360a5750613606826001600160ff1b03613c4d565b8313155b8061362d575060008212801561362d575061362982600160ff1b613c4d565b8312155b6136835760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b60648201526084016107b7565b60006128bc8385613b27565b50805460008255906000526020600020908101906119c791906136f8565b8280548282559060005260206000209081019282156136e8579160200282015b828111156136e85782518255916020019190600101906136cd565b506136f49291506136f8565b5090565b5b808211156136f457600081556001016136f9565b80356001600160a01b038116811461372457600080fd5b919050565b60008083601f84011261373b57600080fd5b5081356001600160401b0381111561375257600080fd5b6020830191508360208260051b850101111561376d57600080fd5b9250929050565b803563ffffffff8116811461372457600080fd5b60006020828403121561379a57600080fd5b6129e78261370d565b600080604083850312156137b657600080fd5b6137bf8361370d565b91506137cd6020840161370d565b90509250929050565b6000806000606084860312156137eb57600080fd5b6137f48461370d565b92506138026020850161370d565b9150604084013590509250925092565b60008060006060848603121561382757600080fd5b6138308461370d565b9250602084013561384081613dd4565b915061384e60408501613774565b90509250925092565b6000806040838503121561386a57600080fd5b6138738361370d565b946020939093013593505050565b6000806040838503121561389457600080fd5b61389d8361370d565b91506137cd60208401613774565b600080600080600080600080600060c08a8c0312156138c957600080fd5b89356001600160401b03808211156138e057600080fd5b6138ec8d838e01613729565b909b50995060208c013591508082111561390557600080fd5b6139118d838e01613729565b909950975060408c013591508082111561392a57600080fd5b506139378c828d01613729565b909650945061394a905060608b01613774565b925061395860808b01613774565b915061396660a08b01613774565b90509295985092959850929598565b60006020828403121561398757600080fd5b81516129e781613dd4565b600080600080600060a086880312156139aa57600080fd5b85356001600160801b03811681146139c157600080fd5b94506139cf60208701613774565b93506139dd60408701613774565b92506139eb60608701613774565b91506139f960808701613774565b90509295509295909350565b600060208284031215613a1757600080fd5b5035919050565b600060208284031215613a3057600080fd5b5051919050565b60008060408385031215613a4a57600080fd5b50508035926020909101359150565b600060208284031215613a6b57600080fd5b813569ffffffffffffffffffff811681146129e757600080fd5b6020808252825182820181905260009190848201906040850190845b81811015613ac65783516001600160a01b031683529284019291840191600101613aa1565b50909695505050505050565b600060208083528351808285015260005b81811015613aff57858101830151858201604001528201613ae3565b81811115613b11576000604083870101525b50601f01601f1916929092016040019392505050565b600080821280156001600160ff1b0384900385131615613b4957613b49613d7c565b600160ff1b8390038412811615613b6257613b62613d7c565b50500190565b60006001600160801b03808316818516808303821115613b8a57613b8a613d7c565b01949350505050565b60008219821115613ba657613ba6613d7c565b500190565b600063ffffffff808316818516808303821115613b8a57613b8a613d7c565b60006001600160401b03808316818516808303821115613b8a57613b8a613d7c565b600082613bfb57613bfb613d92565b600160ff1b821460001984141615613c1557613c15613d7c565b500590565b600082613c2957613c29613d92565b500490565b6000816000190483118215151615613c4857613c48613d7c565b500290565b60008083128015600160ff1b850184121615613c6b57613c6b613d7c565b6001600160ff1b0384018313811615613c8657613c86613d7c565b50500390565b60006001600160801b0383811690831681811015613cac57613cac613d7c565b039392505050565b600082821015613cc657613cc6613d7c565b500390565b600063ffffffff83811690831681811015613cac57613cac613d7c565b600181811c90821680613cfc57607f821691505b60208210811415613d1d57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613d3757613d37613d7c565b5060010190565b600082613d4d57613d4d613d92565b500790565b600082613d6157613d61613d92565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b80151581146119c757600080fdfea2646970667358221220db9f4ee45222520d80751b28b86b958a483e34c1524fd061d8029a3b63ed430e64736f6c634300080600330000000000000000000000004084ab20f8ffca76c19aaf854fb5fe9de6217fbb00000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000055052494345000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106102485760003560e01c806370dea79a1161013b578063b633620c116100b8578063d4cc54e41161007c578063d4cc54e414610654578063e2e403171461066c578063e9ee6eeb1461069e578063f2fde38b146106b1578063feaf968c146106c457600080fd5b8063b633620c146105f1578063b7e2a68a14610604578063c107532914610617578063c35905c61461062a578063c93745001461063d57600080fd5b806388aa80e7116100ff57806388aa80e7146104f05780638da5cb5b1461056057806398e5b12a146105715780639a6fc8f514610594578063b5ab58dc146105de57600080fd5b806370dea79a1461045d578063715018a6146104745780637284e4161461047c5780637c2b0b21146104915780638205bf6a146104b857600080fd5b806340884c52116101c957806358609e441161018d57806358609e44146103e0578063613d8fcc146103f7578063628806ef146103ff57806364efb22b14610412578063668a0f021461044757600080fd5b806340884c521461037157806346fcff4c146103865780634f8fc3b5146103ab57806350d25bcd146103b357806354fd4d50146103d857600080fd5b8063357ebb0211610210578063357ebb02146102e157806338aa4c721461030d5780633969c20f146103205780633a5381b5146103335780633d3d77141461035e57600080fd5b80631327d3d81461024d578063202ee0ed1461026257806320ed02751461027557806323ca290314610288578063313ce567146102c2575b600080fd5b61026061025b366004613788565b6106cc565b005b610260610270366004613a37565b61073d565b610260610283366004613812565b61088f565b6102af7f00000000000000000000000000000000000000000000000000000000000003e881565b6040519081526020015b60405180910390f35b6004546102cf9060ff1681565b60405160ff90911681526020016102b9565b6003546102f890600160c01b900463ffffffff1681565b60405163ffffffff90911681526020016102b9565b61026061031b366004613992565b610984565b61026061032e3660046138ab565b610cbf565b600254610346906001600160a01b031681565b6040516001600160a01b0390911681526020016102b9565b61026061036c3660046137d6565b610e69565b61037961104b565b6040516102b99190613a85565b600c546001600160801b03165b6040516001600160801b0390911681526020016102b9565b6102606110ad565b600654640100000000900463ffffffff166000908152600860205260409020546102af565b6102af600381565b6003546102f890600160801b900463ffffffff1681565b600b546102cf565b61026061040d366004613788565b6111bd565b610346610420366004613788565b6001600160a01b039081166000908152600760205260409020600201546201000090041690565b600654640100000000900463ffffffff166102af565b6003546102f890600160e01b900463ffffffff1681565b61026061129e565b6104846112b2565b6040516102b99190613ad2565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b600654640100000000900463ffffffff16600090815260086020526040902060010154600160401b90046001600160401b03166102af565b6105036104fe366004613881565b611340565b60408051981515895263ffffffff9097166020890152958701949094526001600160401b039283166060870152911660808501526001600160801b0390811660a085015260ff90911660c08401521660e0820152610100016102b9565b6000546001600160a01b0316610346565b61057961149d565b60405169ffffffffffffffffffff90911681526020016102b9565b6105a76105a2366004613a59565b6115a8565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016102b9565b6102af6105ec366004613a05565b6116ae565b6102af6105ff366004613a05565b6116e4565b600154610346906001600160a01b031681565b610260610625366004613857565b611725565b600354610393906001600160801b031681565b6003546102f890600160a01b900463ffffffff1681565b600c54600160801b90046001600160801b0316610393565b6102af61067a366004613788565b6001600160a01b03166000908152600760205260409020546001600160801b031690565b6102606106ac3660046137a3565b611875565b6102606106bf366004613788565b611951565b6105a76119ca565b6106d4611a04565b6002546001600160a01b03908116908216811461073957600280546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fcfac5dc75b8d9a7e074162f59d9adcd33da59f0fe8dfb21580db298fc0fdad0d90600090a35b5050565b60006107493384611a5e565b90507f00000000000000000000000000000000000000000000000000000000000000008212156107c05760405162461bcd60e51b815260206004820152601e60248201527f76616c75652062656c6f77206d696e5375626d697373696f6e56616c7565000060448201526064015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000003e88213156108305760405162461bcd60e51b815260206004820152601e60248201527f76616c75652061626f7665206d61785375626d697373696f6e56616c7565000060448201526064016107b7565b80518190156108525760405162461bcd60e51b81526004016107b79190613ad2565b5061085c83611ced565b6108668284611d8b565b60008061087285611e71565b9150915061087f85611fcf565b610888856120e5565b5050505050565b610897611a04565b6001600160a01b0383166000908152600a602052604090205460ff16151582151514156108c357505050565b811561090a576001600160a01b0383166000908152600a60205260409020805464ffffffffff191683151564ffffffff0019161761010063ffffffff841602179055610933565b6001600160a01b0383166000908152600a60205260409020805468ffffffffffffffffff191690555b60408051831515815263ffffffff831660208201526001600160a01b038516917fc3df5a754e002718f2e10804b99e6605e7c701d95cec9552c7680ca2b6f2820a910160405180910390a25b505050565b61098c611a04565b6000610997600b5490565b60ff1690508463ffffffff168463ffffffff1610156109f85760405162461bcd60e51b815260206004820152601960248201527f6d6178206d75737420657175616c2f657863656564206d696e0000000000000060448201526064016107b7565b8363ffffffff168163ffffffff161015610a545760405162461bcd60e51b815260206004820152601760248201527f6d61782063616e6e6f742065786365656420746f74616c00000000000000000060448201526064016107b7565b63ffffffff81161580610a7257508263ffffffff168163ffffffff16115b610abe5760405162461bcd60e51b815260206004820152601960248201527f64656c61792063616e6e6f742065786365656420746f74616c0000000000000060448201526064016107b7565b610ad0866001600160801b0316612142565b600c546001600160801b03161015610b2a5760405162461bcd60e51b815260206004820152601e60248201527f696e73756666696369656e742066756e647320666f72207061796d656e74000060448201526064016107b7565b6000610b35600b5490565b60ff161115610b945760008563ffffffff1611610b945760405162461bcd60e51b815260206004820152601a60248201527f6d696e206d7573742062652067726561746572207468616e203000000000000060448201526064016107b7565b85600360006101000a8154816001600160801b0302191690836001600160801b0316021790555084600360146101000a81548163ffffffff021916908363ffffffff16021790555083600360106101000a81548163ffffffff021916908363ffffffff16021790555082600360186101000a81548163ffffffff021916908363ffffffff160217905550816003601c6101000a81548163ffffffff021916908363ffffffff1602179055508363ffffffff168563ffffffff16600360009054906101000a90046001600160801b03166001600160801b03167f56800c9d1ed723511246614d15e58cfcde15b6a33c245b5c961b689c1890fd8f8686604051610caf92919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505050565b610cc7611a04565b60005b88811015610d1357610d018a8a83818110610ce757610ce7613dbe565b9050602002016020810190610cfc9190613788565b612166565b80610d0b81613d23565b915050610cca565b50858414610d635760405162461bcd60e51b815260206004820181905260248201527f6e6565642073616d65206f7261636c6520616e642061646d696e20636f756e7460448201526064016107b7565b604d86610d6f600b5490565b60ff16610d7c9190613b93565b1115610dc05760405162461bcd60e51b81526020600482015260136024820152721b585e081bdc9858db195cc8185b1b1bddd959606a1b60448201526064016107b7565b60005b86811015610e3357610e21888883818110610de057610de0613dbe565b9050602002016020810190610df59190613788565b878784818110610e0757610e07613dbe565b9050602002016020810190610e1c9190613788565b612338565b80610e2b81613d23565b915050610dc3565b50600354610e5e906001600160801b03811690859085908590600160e01b900463ffffffff16610984565b505050505050505050565b6001600160a01b03838116600090815260076020526040902060020154620100009004163314610ed45760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b60448201526064016107b7565b6001600160a01b03831660009081526007602052604090205481906001600160801b03908116908216811015610f4c5760405162461bcd60e51b815260206004820152601f60248201527f696e73756666696369656e7420776974686472617761626c652066756e64730060448201526064016107b7565b610f568282613c8c565b6001600160a01b038616600090815260076020526040902080546001600160801b0319166001600160801b03928316179055600c54610f9e918491600160801b900416613c8c565b600c80546001600160801b03928316600160801b0290831617905560015460405163a9059cbb60e01b81526001600160a01b038781166004830152928516602482015291169063a9059cbb90604401602060405180830381600087803b15801561100757600080fd5b505af115801561101b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103f9190613975565b61088857610888613d66565b6060600b8054806020026020016040519081016040528092919081815260200182805480156110a357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611085575b5050505050905090565b604080518082018252600c546001600160801b038082168352600160801b909104166020820181905260015492516370a0823160e01b815230600482015291926000926001600160a01b03909116906370a082319060240160206040518083038186803b15801561111d57600080fd5b505afa158015611131573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111559190613a1e565b61115f9190613cb4565b82519091506001600160801b0316811461073957600c80546001600160801b0319166001600160801b03831617905560405181907ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f90600090a25050565b6001600160a01b038181166000908152600760205260409020600301541633146112295760405162461bcd60e51b815260206004820152601e60248201527f6f6e6c792063616c6c61626c652062792070656e64696e672061646d696e000060448201526064016107b7565b6001600160a01b0381166000818152600760205260408082206003810180546001600160a01b0319169055600201805462010000600160b01b031916336201000081029190911790915590519092917f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90491a350565b6112a6611a04565b6112b060006125bd565b565b600580546112bf90613ce8565b80601f01602080910402602001604051908101604052809291908181526020018280546112eb90613ce8565b80156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b505050505081565b6000808080808080803332146113915760405162461bcd60e51b81526020600482015260166024820152756f66662d636861696e2072656164696e67206f6e6c7960501b60448201526064016107b7565b63ffffffff8916156114765763ffffffff8916600090815260086020908152604080832060099092529091206113c78c8c61260d565b6001600160a01b038d1660009081526007602052604090206001908101548482015491840154600c548f936001600160401b03169163ffffffff600160401b90910416906001600160801b031661141d600b5490565b60018901546001600160401b0316611440576003546001600160801b0316611456565b6001880154600160601b90046001600160801b03165b8363ffffffff169350995099509950995099509950995099505050611490565b61147f8a612677565b975097509750975097509750975097505b9295985092959890939650565b336000908152600a602052604081205460ff166114fc5760405162461bcd60e51b815260206004820152601860248201527f6e6f7420617574686f72697a656420726571756573746572000000000000000060448201526064016107b7565b60065463ffffffff16600081815260086020526040902060010154600160401b90046001600160401b0316151580611538575061153881612845565b6115845760405162461bcd60e51b815260206004820152601f60248201527f7072657620726f756e64206d75737420626520737570657273656461626c650060448201526064016107b7565b6000611591826001613bab565b905061159c816128c4565b63ffffffff1692915050565b63ffffffff80821660009081526008602090815260408083208151608081018352815481526001909101546001600160401b0380821694830194909452600160401b810490931691810191909152600160801b90910490921660608301819052909182918291829182919015801590611631575069ffffffffffffffffffff871663ffffffff10155b6040518060400160405280600f81526020016e139bc819185d18481c1c995cd95b9d608a1b815250906116775760405162461bcd60e51b81526004016107b79190613ad2565b50805160208201516040830151606090930151989991986001600160401b0391821698509216955063ffffffff9091169350915050565b60006116be8263ffffffff101590565b156116dc575063ffffffff1660009081526008602052604090205490565b506000919050565b60006116f48263ffffffff101590565b156116dc575063ffffffff16600090815260086020526040902060010154600160401b90046001600160401b031690565b61172d611a04565b600c546003546001600160801b0391821691839161174b9116612142565b6117559083613cb4565b10156117a35760405162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420726573657276652066756e647300000000000060448201526064016107b7565b60015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb90604401602060405180830381600087803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118299190613975565b61186d5760405162461bcd60e51b81526020600482015260156024820152741d1bdad95b881d1c985b9cd9995c8819985a5b1959605a1b60448201526064016107b7565b61097f6110ad565b6001600160a01b038281166000908152600760205260409020600201546201000090041633146118e05760405162461bcd60e51b815260206004820152601660248201527537b7363c9031b0b63630b1363290313c9030b236b4b760511b60448201526064016107b7565b6001600160a01b0382811660008181526007602090815260409182902060030180546001600160a01b031916948616948517905581513381529081019390935290917fb79bf2e89c2d70dde91d2991fb1ea69b7e478061ad7c04ed5b02b96bc52b8104910160405180910390a25050565b611959611a04565b6001600160a01b0381166119be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107b7565b6119c7816125bd565b50565b60008060008060006119f3600660049054906101000a900463ffffffff1663ffffffff166115a8565b945094509450945094509091929394565b6000546001600160a01b031633146112b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107b7565b6001600160a01b03821660009081526007602052604090205460065460609163ffffffff600160801b9091048116911681611ac757604051806040016040528060128152602001716e6f7420656e61626c6564206f7261636c6560701b81525092505050611ce7565b8363ffffffff168263ffffffff161115611b1357604051806040016040528060168152602001756e6f742079657420656e61626c6564206f7261636c6560501b81525092505050611ce7565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160a01b909204161015611b82576040518060400160405280601881526020017f6e6f206c6f6e67657220616c6c6f776564206f7261636c65000000000000000081525092505050611ce7565b6001600160a01b03851660009081526007602052604090205463ffffffff808616600160c01b9092041610611bf0576040518060400160405280602081526020017f63616e6e6f74207265706f7274206f6e2070726576696f757320726f756e647381525092505050611ce7565b8063ffffffff168463ffffffff1614158015611c225750611c12816001613bab565b63ffffffff168463ffffffff1614155b8015611c355750611c33848261299a565b155b15611c79576040518060400160405280601781526020017f696e76616c696420726f756e6420746f207265706f727400000000000000000081525092505050611ce7565b8363ffffffff16600114158015611ca05750611c9e611c99600186613ccb565b6129ee565b155b15611ce4576040518060400160405280601f81526020017f70726576696f757320726f756e64206e6f7420737570657273656461626c650081525092505050611ce7565b50505b92915050565b611cf681612a28565b611cfd5750565b3360009081526007602052604090205460035463ffffffff600160e01b909204821691611d3291600160c01b90041682613b93565b8263ffffffff1611158015611d4657508015155b15611d4f575050565b611d5882612a54565b50336000908152600760205260409020805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b63ffffffff80821660009081526009602052604090206001015416611df25760405162461bcd60e51b815260206004820152601f60248201527f726f756e64206e6f7420616363657074696e67207375626d697373696f6e730060448201526064016107b7565b63ffffffff8116600081815260096020908152604080832080546001808201835591855283852001879055338085526007909352818420805463ffffffff60c01b1916600160c01b8702178155018690555190929185917f92e98423f8adac6e64d0608e519fd1cefb861498385c6dee70d58fc926ddc68c9190a45050565b63ffffffff80821660009081526009602052604081206001810154905491928392640100000000909204161115611ead57506000928392509050565b63ffffffff831660009081526009602090815260408083208054825181850281018501909352808352611f1393830182828015611f0957602002820191906000526020600020905b815481526020019060010190808311611ef5575b5050505050612bdf565b63ffffffff851660008181526008602090815260409182902084815560010180546bffffffffffffffffffffffff60401b1916600160401b426001600160401b0381169190910263ffffffff60801b191691909117600160801b8602179091556006805467ffffffff00000000191664010000000086021790559151918252929350909183917f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f910160405180910390a3600194909350915050565b63ffffffff8116600090815260096020908152604091829020600101548251808401909352600c546001600160801b03808216808652600160801b909204811693850193909352600160601b909104909116919061202e908390613c8c565b6001600160801b031681526020810151612049908390613b68565b6001600160801b03908116602083810182905283518316600160801b90920291909117600c553360009081526007909152604090205461208b91849116613b68565b3360009081526007602052604080822080546001600160801b0319166001600160801b03948516179055835190519216917ffe25c73e3b9089fac37d55c4c7efcba6f04af04cebd2fc4d6d7dbb07e1e5234f9190a2505050565b63ffffffff8082166000908152600960205260409020600181015490549116111561210d5750565b63ffffffff811660009081526009602052604081209061212d828261368f565b5060010180546001600160e01b031916905550565b6000600261214f600b5490565b61215c9060ff1684613c2e565b611ce79190613c2e565b61216f81612c9f565b6121b05760405162461bcd60e51b81526020600482015260126024820152711bdc9858db19481b9bdd08195b98589b195960721b60448201526064016107b7565b6006546121c49063ffffffff166001613bab565b6001600160a01b0382166000908152600760205260408120805463ffffffff93909316600160a01b0263ffffffff60a01b1990931692909217909155600b600161220d600b5490565b60ff1661221a9190613cb4565b8154811061222a5761222a613dbe565b6000918252602080832091909101546001600160a01b0385811680855260079093526040808520600290810180549390941680875291862001805461ffff90931661ffff199384168117909155939094528154169055600b805492935090918391908390811061229c5761229c613dbe565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b8054806122db576122db613da8565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516907f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e908390a3505050565b61234182612c9f565b156123875760405162461bcd60e51b81526020600482015260166024820152751bdc9858db1948185b1c9958591e48195b98589b195960521b60448201526064016107b7565b6001600160a01b0381166123d55760405162461bcd60e51b8152602060048201526015602482015274063616e6e6f74207365742061646d696e20746f203605c1b60448201526064016107b7565b6001600160a01b0382811660009081526007602052604090206002015462010000900416158061242a57506001600160a01b038281166000908152600760205260409020600201546201000090048116908216145b6124765760405162461bcd60e51b815260206004820152601c60248201527f6f776e65722063616e6e6f74206f76657277726974652061646d696e0000000060448201526064016107b7565b61247f82612cca565b6001600160a01b03838116600081815260076020526040808220805463ffffffff60a01b1963ffffffff97909716600160801b029690961667ffffffffffffffff60801b199096169590951763ffffffff60a01b178555600b80546002909601805461ffff90971661ffff19909716969096178655805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b031916851790558554948716620100000262010000600160b01b0319909516949094179094559251919290917f18dd09695e4fbdae8d1a5edb11221eb04564269c29a089b9753a6535c54ba92e9190a3806001600160a01b0316826001600160a01b03167f0c5055390645c15a4be9a21b3f8d019153dcb4a0c125685da6eb84048e2fe90460405160405180910390a35050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b63ffffffff81166000908152600860205260408120600101546001600160401b03161561266d5763ffffffff8083166000908152600960205260409020600101541615155b801561266657506126638383611a5e565b51155b9050611ce7565b6126528383612d22565b6001600160a01b0381166000908152600760205260408120600654815483928392839283928392839283927f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7929091849163ffffffff908116600160c01b909204161480612700575060065463ffffffff90811660009081526009602052604090206001015416155b6006549091506127159063ffffffff166129ee565b801561271e5750805b15612772576006546127379063ffffffff166001613bab565b63ffffffff81166000908152600860205260409020600354919b506001600160801b039091169450925061276b8c8b612d22565b9a506127b7565b60065463ffffffff9081166000818152600860209081526040808320600990925290912060010154919c50600160601b82046001600160801b0316965094501615159a505b6127c18c8b611a5e565b51156127cc5760009a505b6001808301548482015463ffffffff808e16600090815260096020526040902090930154600c548f948f94936001600160401b031692600160401b900416906001600160801b031661281d600b5490565b8a8363ffffffff1693509a509a509a509a509a509a509a509a50505050919395975091939597565b63ffffffff80821660009081526008602090815260408083206001908101546009909352908320015491926001600160401b0390911691600160401b9004168115801590612899575060008163ffffffff16115b80156128bc5750426128b163ffffffff831684613bca565b6001600160401b0316105b949350505050565b6128cd81612a28565b6128d45750565b336000908152600a602052604090205463ffffffff650100000000008204811691612906916101009091041682613b93565b8263ffffffff161180612917575080155b6129595760405162461bcd60e51b81526020600482015260136024820152726d7573742064656c617920726571756573747360681b60448201526064016107b7565b61296282612a54565b50336000908152600a60205260409020805463ffffffff909216650100000000000268ffffffff000000000019909216919091179055565b600063ffffffff82166129ae846001613bab565b63ffffffff161480156129e7575063ffffffff8216600090815260086020526040902060010154600160401b90046001600160401b0316155b9392505050565b63ffffffff8116600090815260086020526040812060010154600160401b90046001600160401b0316151580611ce75750611ce782612845565b600654600090612a3f9063ffffffff166001613bab565b63ffffffff168263ffffffff16149050919050565b612a67612a62600183613ccb565b612d76565b6006805463ffffffff191663ffffffff83811691821790925560408051600060a0820181815260c0830184528252600354600160801b81048616602080850191909152600160a01b8204871684860152600160e01b820490961660608401526001600160801b031660808301529283526009845291208151805192938493612af292849201906136ad565b506020828101516001928301805460408087015160608801516080909801516001600160801b0316600160601b026fffffffffffffffffffffffffffffffff60601b1963ffffffff998a16600160401b021668010000000000000000600160e01b0319928a166401000000000267ffffffffffffffff19958616978b16979097179690961791909116949094179390931790915593861660008181526008845282902090930180546001600160401b0342169516851790555192835233927f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271910160405180910390a35050565b60008151600010612c2b5760405162461bcd60e51b81526020600482015260166024820152756c697374206d757374206e6f7420626520656d70747960501b60448201526064016107b7565b81516000612c3a600283613c1a565b9050612c47600283613d52565b612c8857600080612c6f8682612c5e600188613cb4565b612c69600188613cb4565b87612e39565b9092509050612c7e8282612f31565b9695505050505050565b6128bc846000612c99600186613cb4565b84612fc9565b6001600160a01b0316600090815260076020526040902054600160a01b900463ffffffff9081161490565b60065460009063ffffffff168015801590612d0c57506001600160a01b03831660009081526007602052604090205463ffffffff828116600160a01b90920416145b15612d175792915050565b6129e7816001613bab565b6001600160a01b03821660009081526007602052604081205460035463ffffffff600160e01b909204821691612d6091600160c01b90041682613b93565b8363ffffffff1611806128bc5750159392505050565b612d7f81612845565b612d865750565b6000612d93600183613ccb565b63ffffffff818116600090815260086020908152604080832080548886168552828520908155600191820154910180546bffffffffffffffffffffffff60401b1916600160801b928390049096169091026fffffffffffffffff0000000000000000191694909417600160401b426001600160401b0316021790935560099052908120919250612e23828261368f565b5060010180546001600160e01b03191690555050565b600080828410612e4857600080fd5b838611158015612e585750848411155b612e6157600080fd5b828611158015612e715750848311155b612e7a57600080fd5b6007612e868787613cb4565b1015612ea257612e99878787878761306e565b91509150612f27565b6000612eaf8888886134b8565b9050808411612ec057809550612f21565b84811015612eda57612ed3816001613b93565b9650612f21565b808511158015612ee957508381105b612ef557612ef5613d66565b612f0188888388612fc9565b9250612f1988612f12836001613b93565b8887612fc9565b915050612f27565b50612e7a565b9550959350505050565b60008083128015612f425750600082135b80612f585750600083138015612f585750600082125b15612f73576002612f6984846135e8565b6126669190613bec565b60006002612f818185613d3e565b612f8c600287613d3e565b612f969190613b27565b612fa09190613bec565b90506128bc612fc3612fb3600287613bec565b612fbe600287613bec565b6135e8565b826135e8565b600081841115612fd857600080fd5b82821115612fe557600080fd5b8284101561304a576007612ff98585613cb4565b101561301857600061300e868686868761306e565b5091506128bc9050565b60006130258686866134b8565b905080831161303657809350613044565b613041816001613b93565b94505b50612fe5565b84848151811061305c5761305c613dbe565b60200260200101519050949350505050565b600080808661307e876001613b93565b6130889190613cb4565b90506000886130978983613b93565b815181106130a7576130a7613dbe565b602002602001015190506000826001106130c8576001600160ff1b036130ed565b896130d48a6001613b93565b815181106130e4576130e4613dbe565b60200260200101515b9050600083600210613106576001600160ff1b0361312b565b8a6131128b6002613b93565b8151811061312257613122613dbe565b60200260200101515b9050600084600310613144576001600160ff1b03613169565b8b6131508c6003613b93565b8151811061316057613160613dbe565b60200260200101515b9050600085600410613182576001600160ff1b036131a7565b8c61318e8d6004613b93565b8151811061319e5761319e613dbe565b60200260200101515b90506000866005106131c0576001600160ff1b036131e5565b8d6131cc8e6005613b93565b815181106131dc576131dc613dbe565b60200260200101515b90506000876006106131fe576001600160ff1b03613223565b8e61320a8f6006613b93565b8151811061321a5761321a613dbe565b60200260200101515b905085871315613231579495945b8385131561323d579293925b81831315613249579091905b84871315613255579395935b83861315613261579294925b8083131561326b57915b84861315613277579394935b8082131561328157905b8287131561328d579195915b81861315613299579094905b808513156132a357935b828613156132af579194915b808413156132b957925b828513156132c5579193915b818413156132d1579092905b828413156132dd579192915b60006132e98f8e613cb4565b9050806132f857879a50613399565b806001141561330957869a50613399565b806002141561331a57859a50613399565b806003141561332b57849a50613399565b806004141561333c57839a50613399565b806005141561334d57829a50613399565b806006141561335e57819a50613399565b60405162461bcd60e51b815260206004820152601060248201526f6b31206f7574206f6620626f756e647360801b60448201526064016107b7565b60008f8d6133a79190613cb4565b90508c8e14156133c457508a9950612f2798505050505050505050565b806133db5750969850612f27975050505050505050565b80600114156133f65750959850612f27975050505050505050565b80600214156134115750949850612f27975050505050505050565b806003141561342c5750939850612f27975050505050505050565b80600414156134475750929850612f27975050505050505050565b80600514156134625750919850612f27975050505050505050565b806006141561347d5750909850612f27975050505050505050565b60405162461bcd60e51b815260206004820152601060248201526f6b32206f7574206f6620626f756e647360801b60448201526064016107b7565b6000808460026134c88587613b93565b6134d29190613c1a565b815181106134e2576134e2613dbe565b602002602001015190506001846134f99190613cb4565b9350613506600184613b93565b92505b613514600185613b93565b93508085858151811061352957613529613dbe565b602002602001015112613509575b613542600184613cb4565b92508085848151811061355757613557613dbe565b60200260200101511361353757828410156135df5784838151811061357e5761357e613dbe565b602002602001015185858151811061359857613598613dbe565b60200260200101518686815181106135b2576135b2613dbe565b602002602001018786815181106135cb576135cb613dbe565b602090810291909101019190915252613509565b50909392505050565b600080821215801561360a5750613606826001600160ff1b03613c4d565b8313155b8061362d575060008212801561362d575061362982600160ff1b613c4d565b8312155b6136835760405162461bcd60e51b815260206004820152602160248201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6044820152607760f81b60648201526084016107b7565b60006128bc8385613b27565b50805460008255906000526020600020908101906119c791906136f8565b8280548282559060005260206000209081019282156136e8579160200282015b828111156136e85782518255916020019190600101906136cd565b506136f49291506136f8565b5090565b5b808211156136f457600081556001016136f9565b80356001600160a01b038116811461372457600080fd5b919050565b60008083601f84011261373b57600080fd5b5081356001600160401b0381111561375257600080fd5b6020830191508360208260051b850101111561376d57600080fd5b9250929050565b803563ffffffff8116811461372457600080fd5b60006020828403121561379a57600080fd5b6129e78261370d565b600080604083850312156137b657600080fd5b6137bf8361370d565b91506137cd6020840161370d565b90509250929050565b6000806000606084860312156137eb57600080fd5b6137f48461370d565b92506138026020850161370d565b9150604084013590509250925092565b60008060006060848603121561382757600080fd5b6138308461370d565b9250602084013561384081613dd4565b915061384e60408501613774565b90509250925092565b6000806040838503121561386a57600080fd5b6138738361370d565b946020939093013593505050565b6000806040838503121561389457600080fd5b61389d8361370d565b91506137cd60208401613774565b600080600080600080600080600060c08a8c0312156138c957600080fd5b89356001600160401b03808211156138e057600080fd5b6138ec8d838e01613729565b909b50995060208c013591508082111561390557600080fd5b6139118d838e01613729565b909950975060408c013591508082111561392a57600080fd5b506139378c828d01613729565b909650945061394a905060608b01613774565b925061395860808b01613774565b915061396660a08b01613774565b90509295985092959850929598565b60006020828403121561398757600080fd5b81516129e781613dd4565b600080600080600060a086880312156139aa57600080fd5b85356001600160801b03811681146139c157600080fd5b94506139cf60208701613774565b93506139dd60408701613774565b92506139eb60608701613774565b91506139f960808701613774565b90509295509295909350565b600060208284031215613a1757600080fd5b5035919050565b600060208284031215613a3057600080fd5b5051919050565b60008060408385031215613a4a57600080fd5b50508035926020909101359150565b600060208284031215613a6b57600080fd5b813569ffffffffffffffffffff811681146129e757600080fd5b6020808252825182820181905260009190848201906040850190845b81811015613ac65783516001600160a01b031683529284019291840191600101613aa1565b50909695505050505050565b600060208083528351808285015260005b81811015613aff57858101830151858201604001528201613ae3565b81811115613b11576000604083870101525b50601f01601f1916929092016040019392505050565b600080821280156001600160ff1b0384900385131615613b4957613b49613d7c565b600160ff1b8390038412811615613b6257613b62613d7c565b50500190565b60006001600160801b03808316818516808303821115613b8a57613b8a613d7c565b01949350505050565b60008219821115613ba657613ba6613d7c565b500190565b600063ffffffff808316818516808303821115613b8a57613b8a613d7c565b60006001600160401b03808316818516808303821115613b8a57613b8a613d7c565b600082613bfb57613bfb613d92565b600160ff1b821460001984141615613c1557613c15613d7c565b500590565b600082613c2957613c29613d92565b500490565b6000816000190483118215151615613c4857613c48613d7c565b500290565b60008083128015600160ff1b850184121615613c6b57613c6b613d7c565b6001600160ff1b0384018313811615613c8657613c86613d7c565b50500390565b60006001600160801b0383811690831681811015613cac57613cac613d7c565b039392505050565b600082821015613cc657613cc6613d7c565b500390565b600063ffffffff83811690831681811015613cac57613cac613d7c565b600181811c90821680613cfc57607f821691505b60208210811415613d1d57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613d3757613d37613d7c565b5060010190565b600082613d4d57613d4d613d92565b500790565b600082613d6157613d61613d92565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b80151581146119c757600080fdfea2646970667358221220db9f4ee45222520d80751b28b86b958a483e34c1524fd061d8029a3b63ed430e64736f6c63430008060033