Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- FetchFlex
- Optimization enabled
- true
- Compiler version
- v0.8.20+commit.a1b79de6
- Optimization runs
- 300
- EVM Version
- default
- Verified at
- 2025-01-23T00:38:12.314558Z
fetchflex/contracts/FetchFlex.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "./interfaces/IFetchToken.sol";
import "./dependencies/upgrades/Initializable.sol";
import "./dependencies/upgrades/UUPSUpgradeable.sol";
import "./dependencies/upgrades/OwnableUpgradeable.sol";
import "./dependencies/utils/EnumerableSet.sol";
/**
@author Fetch Inc.
@title FetchFlex
@dev This is a streamlined Fetch oracle system which handles staking, reporting,
* slashing, and user data getters in one contract. This contract is controlled
* by a single address known as 'governance', which could be an externally owned
* account or a contract, allowing for a flexible, modular design.
*/
contract FetchFlex is Initializable, OwnableUpgradeable, UUPSUpgradeable{
using EnumerableSet for EnumerableSet.AddressSet;
// Storage
IFetchToken public token; // token used for staking and rewards
address public governance; // address with ability to remove values and slash reporters
uint256 public accumulatedRewardPerShare; // accumulated staking reward per staked token
uint256 public minimumStakeAmount; // minimum amount of tokens required to stake
uint256 public reportingLock; // base amount of time before a reporter is able to submit a value again
uint256 public rewardRate; // total staking rewards released per second
uint256 public stakeAmount; // minimum amount required to be a staker
uint256 public stakeAmountDollarTarget; // amount of US dollars required to be a staker
uint256 public stakingRewardsBalance; // total amount of staking rewards
bytes32 public stakingTokenPriceQueryId; // staking token SpotPrice queryId, used for updating stakeAmount
uint256 public timeOfLastAllocation; // time of last update to accumulatedRewardPerShare
uint256 public timeOfLastNewValue; // time of the last new submitted value, originally set to the block timestamp
uint256 public totalRewardDebt; // staking reward debt, used to calculate real staking rewards balance
uint256 public totalStakeAmount; // total amount of tokens locked in contract (via stake)
uint256 public totalStakers; // total number of stakers with at least stakeAmount staked, not exact
uint256 public toWithdraw; //amountLockedForWithdrawal
uint256 public tokenCreatedAt;
mapping(bytes32 => Report) private reports; // mapping of query IDs to a report
mapping(address => StakeInfo) private stakerDetails; // mapping from a persons address to their staking info
mapping(bytes32 => QueryConfig) private queryConfig; // mapping from a query ID to the config, intended for managed feeds
mapping(bytes32 => EnumerableSet.AddressSet) private managedReporters; // mapping for specific reporters for each managed feed
uint256[63] __reserved; // Reserved slots for future improvements
uint256 public timeOfLastDistribution; // time of last dispersion of time-based rewards
// Structs
struct QueryConfig {
address manager; // The query manager address
mapping(bytes32 => uint) config; // The config for the managed feed (only configurable by feed manager)
}
struct Report {
uint256[] timestamps; // array of all newValueTimestamps reported
mapping(uint256 => uint256) timestampIndex; // mapping of timestamps to respective indices
mapping(uint256 => uint256) timestampToBlockNum; // mapping of timestamp to block number
mapping(uint256 => bytes) valueByTimestamp; // mapping of timestamps to values
mapping(uint256 => address) reporterByTimestamp; // mapping of timestamps to reporters
mapping(uint256 => bool) isDisputed;
}
struct StakeInfo {
uint256 startDate; // stake or withdrawal request start date
uint256 stakedBalance; // staked token balance
uint256 lockedBalance; // amount locked for withdrawal
uint256 rewardDebt; // used for staking reward calculation
uint256 reporterLastTimestamp; // timestamp of reporter's last reported value
uint256 reportsSubmitted; // total number of reports submitted by reporter
uint256 startVoteCount; // total number of governance votes when stake deposited
uint256 startVoteTally; // staker vote tally when stake deposited
bool staked; // used to keep track of total stakers
mapping(bytes32 => uint256) reportsSubmittedByQueryId; // mapping of queryId to number of reports submitted by reporter
}
modifier onlyManager(bytes32 queryId) {
require(msg.sender == queryConfig[queryId].manager);
_;
}
// Events
event NewReport(
bytes32 indexed _queryId,
uint256 indexed _time,
bytes _value,
uint256 _nonce,
bytes _queryData,
address indexed _reporter
);
event NewStakeAmount(uint256 _newStakeAmount, uint256 _stakingTokenPrice);
event NewStaker(address indexed _staker, uint256 indexed _amount);
event ReporterSlashed(
address indexed _reporter,
address _recipient,
uint256 _slashAmount
);
event StakeWithdrawn(address _staker);
event StakeWithdrawRequested(address _staker, uint256 _amount);
event ValueRemoved(bytes32 _queryId, uint256 _timestamp);
event TimeBasedRewardTransfer(address indexed _reporter, uint256 _reward);
event StakingRewardTransfer(address indexed _reporter, uint256 _reward);
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
// Functions
/**
* @dev Initializes system parameters
* @param _token address of token used for staking and rewards
* @param _reportingLock base amount of time (seconds) before reporter is able to report again
* @param _stakeAmountDollarTarget fixed USD amount that stakeAmount targets on updateStakeAmount
* @param _stakingTokenPrice current price of staking token in USD (18 decimals)
* @param _stakingTokenPriceQueryId queryId where staking token price is reported
*/
function initialize(
address _token,
uint256 _reportingLock,
uint256 _stakeAmountDollarTarget,
uint256 _stakingTokenPrice,
uint256 _minimumStakeAmount,
bytes32 _stakingTokenPriceQueryId
) public initializer {
__Ownable_init();
require(_token != address(0), "must set token address");
require(_stakingTokenPrice > 0, "must set staking token price");
require(_reportingLock > 0, "must set reporting lock");
require(_stakingTokenPriceQueryId != bytes32(0), "must set staking token price queryId");
timeOfLastNewValue = block.timestamp;
timeOfLastDistribution = block.timestamp;
token = IFetchToken(_token);
tokenCreatedAt = token.getCreatedAt();
reportingLock = _reportingLock;
stakeAmountDollarTarget = _stakeAmountDollarTarget;
minimumStakeAmount = _minimumStakeAmount;
uint256 _potentialStakeAmount = (_stakeAmountDollarTarget * 1e18) / _stakingTokenPrice;
if(_potentialStakeAmount < _minimumStakeAmount) {
stakeAmount = _minimumStakeAmount;
} else {
stakeAmount = _potentialStakeAmount;
}
stakingTokenPriceQueryId = _stakingTokenPriceQueryId;
}
function _authorizeUpgrade(address _newImplementation) internal virtual override onlyOwner {
require(_isValid(_newImplementation), "invalid oracle address");
}
/**
* @dev Allows the owner to initialize the governance (flex addy needed for governance deployment)
* @param _governanceAddress address of governance contract (github.com/fetchoracle/governance)
*/
function init(address _governanceAddress) external onlyOwner {
require(governance == address(0), "governance address already set");
require(
_governanceAddress != address(0),
"governance address can't be zero address"
);
governance = _governanceAddress;
}
/**
* @dev Funds the Flex contract with staking rewards (paid by autopay and minting)
* @param _amount amount of tokens to fund contract with
*/
function addStakingRewards(uint256 _amount) external {
require(token.transferFrom(msg.sender, address(this), _amount));
_updateRewards();
stakingRewardsBalance += _amount;
// update reward rate = real staking rewards balance / 30 days
rewardRate =
(stakingRewardsBalance -
((accumulatedRewardPerShare * totalStakeAmount) /
1e18 -
totalRewardDebt)) /
30 days;
}
/**
* @dev Allows a reporter to submit stake
* @param _amount amount of tokens to stake
*/
function depositStake(uint256 _amount) external {
require(governance != address(0), "governance address not set");
StakeInfo storage _staker = stakerDetails[msg.sender];
uint256 _stakedBalance = _staker.stakedBalance;
uint256 _lockedBalance = _staker.lockedBalance;
if (_lockedBalance > 0) {
if (_lockedBalance >= _amount) {
// if staker's locked balance covers full _amount, use that
_staker.lockedBalance -= _amount;
toWithdraw -= _amount;
} else {
// otherwise, stake the whole locked balance and transfer the
// remaining amount from the staker's address
require(
token.transferFrom(
msg.sender,
address(this),
_amount - _lockedBalance
)
);
toWithdraw -= _staker.lockedBalance;
_staker.lockedBalance = 0;
}
} else {
if (_stakedBalance == 0) {
// if staked balance and locked balance equal 0, save current vote tally.
// voting participation used for calculating rewards
(bool _success, bytes memory _returnData) = governance.call(
abi.encodeWithSignature("getVoteCount()")
);
if (_success) {
_staker.startVoteCount = uint256(abi.decode(_returnData, (uint256)));
}
(_success,_returnData) = governance.call(
abi.encodeWithSignature("getVoteTallyByAddress(address)",msg.sender)
);
if(_success){
_staker.startVoteTally = abi.decode(_returnData,(uint256));
}
}
require(token.transferFrom(msg.sender, address(this), _amount));
}
_updateStakeAndPayRewards(msg.sender, _stakedBalance + _amount);
_staker.startDate = block.timestamp; // This resets the staker start date to now
emit NewStaker(msg.sender, _amount);
}
/**
* @dev Removes a value from the oracle.
* Note: this function is only callable by the Governance contract.
* @param _queryId is ID of the specific data feed
* @param _timestamp is the timestamp of the data value to remove
*/
function removeValue(bytes32 _queryId, uint256 _timestamp) external {
if (isManagedQuery(_queryId)) {
require(isReporterForQuery(_queryId, msg.sender), "caller must be an authorized reporter");
}
else {
require(msg.sender == governance, "caller must be governance address");
}
Report storage _report = reports[_queryId];
require(!_report.isDisputed[_timestamp], "value already disputed");
uint256 _index = _report.timestampIndex[_timestamp];
require(_timestamp == _report.timestamps[_index], "invalid timestamp");
_report.valueByTimestamp[_timestamp] = "";
_report.isDisputed[_timestamp] = true;
emit ValueRemoved(_queryId, _timestamp);
}
/**
* @dev Allows a reporter to request to withdraw their stake
* @param _amount amount of staked tokens requesting to withdraw
*/
function requestStakingWithdraw(uint256 _amount) external {
StakeInfo storage _staker = stakerDetails[msg.sender];
require(
_staker.stakedBalance >= _amount,
"insufficient staked balance"
);
_updateStakeAndPayRewards(msg.sender, _staker.stakedBalance - _amount);
_staker.startDate = block.timestamp;
_staker.lockedBalance += _amount;
toWithdraw += _amount;
emit StakeWithdrawRequested(msg.sender, _amount);
}
/**
* @dev Slashes a reporter and transfers their stake amount to the given recipient
* Note: this function is only callable by the governance address.
* @param _reporter is the address of the reporter being slashed
* @param _recipient is the address receiving the reporter's stake
* @return _slashAmount uint256 amount of token slashed and sent to recipient address
*/
function slashReporter(address _reporter, address _recipient)
external
returns (uint256 _slashAmount)
{
require(msg.sender == governance, "only governance can slash reporter");
StakeInfo storage _staker = stakerDetails[_reporter];
uint256 _stakedBalance = _staker.stakedBalance;
uint256 _lockedBalance = _staker.lockedBalance;
require(_stakedBalance + _lockedBalance > 0, "zero staker balance");
if (_lockedBalance >= stakeAmount) {
// if locked balance is at least stakeAmount, slash from locked balance
_slashAmount = stakeAmount;
_staker.lockedBalance -= stakeAmount;
toWithdraw -= stakeAmount;
} else if (_lockedBalance + _stakedBalance >= stakeAmount) {
// if locked balance + staked balance is at least stakeAmount,
// slash from locked balance and slash remainder from staked balance
_slashAmount = stakeAmount;
_updateStakeAndPayRewards(
_reporter,
_stakedBalance - (stakeAmount - _lockedBalance)
);
toWithdraw -= _lockedBalance;
_staker.lockedBalance = 0;
} else {
// if sum(locked balance + staked balance) is less than stakeAmount,
// slash sum
_slashAmount = _stakedBalance + _lockedBalance;
toWithdraw -= _lockedBalance;
_updateStakeAndPayRewards(_reporter, 0);
_staker.lockedBalance = 0;
}
require(token.transfer(_recipient, _slashAmount));
emit ReporterSlashed(_reporter, _recipient, _slashAmount);
}
/**
* @dev Allows a reporter to submit a value to the oracle
* @param _queryId is ID of the specific data feed. Equals keccak256(_queryData) for non-legacy IDs
* @param _value is the value the user submits to the oracle
* @param _nonce is the current value count for the query id
* @param _queryData is the data used to fulfill the data query
*/
function submitValue(
bytes32 _queryId,
bytes calldata _value,
uint256 _nonce,
bytes calldata _queryData
) external {
require(keccak256(_value) != keccak256(""), "value must be submitted");
bool isManaged = isManagedQuery(_queryId);
bool requiresStaking = isManaged?
queryConfig[_queryId].config[keccak256("REQUIRES_STAKING")] == 1 :
true;
if (isManaged) {
require(isReporterForQuery(_queryId, msg.sender), "reporter not authorized");
}
if (isManaged) {
uint256 price = abi.decode(_value, (uint256));
require(price > 0, "Invalid price");
}
Report storage _report = reports[_queryId];
require(
_nonce == _report.timestamps.length || _nonce == 0,
"nonce must match timestamp index"
);
StakeInfo storage _staker = stakerDetails[msg.sender];
if (requiresStaking) {
require(
_staker.stakedBalance >= stakeAmount,
"balance must be greater than stake amount"
);
// Require reporter to abide by given reporting lock
require(
(block.timestamp - _staker.reporterLastTimestamp) * 1000 >
(reportingLock * 1000) / (_staker.stakedBalance / stakeAmount),
"still in reporter time lock, please wait!"
);
}
require(
_queryId == keccak256(_queryData),
"query id must be hash of query data"
);
_staker.reporterLastTimestamp = block.timestamp;
// Checks for no double reporting of timestamps
require(
_report.reporterByTimestamp[block.timestamp] == address(0),
"timestamp already reported for"
);
// Update number of timestamps, value for given timestamp, and reporter for timestamp
_report.timestampIndex[block.timestamp] = _report.timestamps.length;
_report.timestamps.push(block.timestamp);
_report.timestampToBlockNum[block.timestamp] = block.number;
_report.valueByTimestamp[block.timestamp] = _value;
_report.reporterByTimestamp[block.timestamp] = msg.sender;
if (requiresStaking) {
token.mintToOracle();
// Disperse Time Based Reward
uint256 _reward = ((block.timestamp - timeOfLastDistribution) * getTimeBasedReward()) / 300;
uint256 _totalTimeBasedRewardsBalance =
token.balanceOf(address(this)) -
(totalStakeAmount + stakingRewardsBalance + toWithdraw);
if (_totalTimeBasedRewardsBalance > 0 && _reward > 0) {
if (_totalTimeBasedRewardsBalance < _reward) {
token.transfer(msg.sender, _totalTimeBasedRewardsBalance);
emit TimeBasedRewardTransfer(msg.sender, _totalTimeBasedRewardsBalance);
} else {
token.transfer(msg.sender, _reward);
emit TimeBasedRewardTransfer(msg.sender, _reward);
}
}
timeOfLastDistribution = block.timestamp;
}
// Update last oracle value and number of values submitted by a reporter
timeOfLastNewValue = block.timestamp;
_staker.reportsSubmitted++;
_staker.reportsSubmittedByQueryId[_queryId]++;
emit NewReport(
_queryId,
block.timestamp,
_value,
_nonce,
_queryData,
msg.sender
);
}
/**
* @dev Updates the stake amount after retrieving the latest
* 12+-hour-old staking token price from the oracle
*/
function updateStakeAmount() external {
// get staking token price
(bool _valFound, bytes memory _val, ) = getDataBefore(
stakingTokenPriceQueryId,
block.timestamp - 12 hours
);
if (_valFound) {
uint256 _stakingTokenPrice = abi.decode(_val, (uint256));
require(
_stakingTokenPrice >= 0.000000001 ether && _stakingTokenPrice < 1000000 ether,
"invalid staking token price"
);
uint256 _adjustedStakeAmount = (stakeAmountDollarTarget * 1e18) / _stakingTokenPrice;
if(_adjustedStakeAmount < minimumStakeAmount) {
stakeAmount = minimumStakeAmount;
} else {
stakeAmount = _adjustedStakeAmount;
}
emit NewStakeAmount(stakeAmount, _stakingTokenPrice);
}
}
/**
* @dev Withdraws a reporter's stake after the lock period expires
*/
function withdrawStake() external {
StakeInfo storage _staker = stakerDetails[msg.sender];
// Ensure reporter is locked and that enough time has passed
require(
block.timestamp - _staker.startDate >= 7 days,
"7 days didn't pass"
);
require(
_staker.lockedBalance > 0,
"reporter not locked for withdrawal"
);
require(token.transfer(msg.sender, _staker.lockedBalance));
toWithdraw -= _staker.lockedBalance;
_staker.lockedBalance = 0;
emit StakeWithdrawn(msg.sender);
}
// *****************************************************************************
// * *
// * Getters *
// * *
// *****************************************************************************
/**
* @dev Returns the block number at a given timestamp
* @param _queryId is ID of the specific data feed
* @param _timestamp is the timestamp to find the corresponding block number for
* @return uint256 block number of the timestamp for the given data ID
*/
function getBlockNumberByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (uint256)
{
return reports[_queryId].timestampToBlockNum[_timestamp];
}
/**
* @dev Returns the current value of a data feed given a specific ID
* @param _queryId is the ID of the specific data feed
* @return _value the latest submitted value for the given queryId
*/
function getCurrentValue(bytes32 _queryId)
external
view
returns (bytes memory _value)
{
bool _didGet;
(_didGet, _value, ) = getDataBefore(_queryId, block.timestamp + 1);
if(!_didGet){revert();}
}
/**
* @dev Retrieves the latest value for the queryId before the specified timestamp
* @param _queryId is the queryId to look up the value for
* @param _timestamp before which to search for latest value
* @return _ifRetrieve bool true if able to retrieve a non-zero value
* @return _value the value retrieved
* @return _timestampRetrieved the value's timestamp
*/
function getDataBefore(bytes32 _queryId, uint256 _timestamp)
public
view
returns (
bool _ifRetrieve,
bytes memory _value,
uint256 _timestampRetrieved
)
{
(bool _found, uint256 _index) = getIndexForDataBefore(
_queryId,
_timestamp
);
if (!_found) return (false, bytes(""), 0);
_timestampRetrieved = getTimestampbyQueryIdandIndex(_queryId, _index);
_value = retrieveData(_queryId, _timestampRetrieved);
return (true, _value, _timestampRetrieved);
}
/**
* @dev Returns governance address
* @return address governance
*/
function getGovernanceAddress() external view returns (address) {
return governance;
}
/**
* @dev Counts the number of values that have been submitted for the request.
* @param _queryId the id to look up
* @return uint256 count of the number of values received for the id
*/
function getNewValueCountbyQueryId(bytes32 _queryId)
public
view
returns (uint256)
{
return reports[_queryId].timestamps.length;
}
/**
* @dev Returns the pending staking reward for a given address
* @param _stakerAddress staker address to look up
* @return _pendingReward - pending reward for given staker
*/
function getPendingRewardByStaker(address _stakerAddress)
external
view
returns (uint256 _pendingReward)
{
StakeInfo storage _staker = stakerDetails[_stakerAddress];
_pendingReward = (_staker.stakedBalance *
_getUpdatedAccumulatedRewardPerShare()) /
1e18 -
_staker.rewardDebt;
(bool _success, bytes memory _returnData) = governance.staticcall(
abi.encodeWithSignature("getVoteCount()")
);
uint256 _numberOfVotes;
if (_success) {
_numberOfVotes = uint256(abi.decode(_returnData, (uint256))) - _staker.startVoteCount;
}
if (_numberOfVotes > 0) {
(_success,_returnData) = governance.staticcall(
abi.encodeWithSignature("getVoteTallyByAddress(address)",_stakerAddress)
);
if(_success){
uint256 _voteTally = abi.decode(_returnData,(uint256));
uint256 _tempPendingReward = (
_pendingReward * (_voteTally - _staker.startVoteTally)
) / _numberOfVotes;
if (_tempPendingReward < _pendingReward) {
_pendingReward = _tempPendingReward;
}
}
}
}
/**
* @dev Returns the real staking rewards balance after accounting for unclaimed rewards
* @return uint256 real staking rewards balance
*/
function getStakingRewardsBalance() internal view returns (uint256) {
uint256 _pendingRewards = (_getUpdatedAccumulatedRewardPerShare() *
totalStakeAmount) /
1e18 -
totalRewardDebt;
return (stakingRewardsBalance - _pendingRewards);
}
/**
* @dev Returns the real staking rewards balance after accounting for unclaimed rewards
* @return uint256 real staking rewards balance
*/
function getRealStakingRewardsBalance() external view returns (uint256) {
return getStakingRewardsBalance();
}
/**
* @dev Returns reporter address and whether a value was removed for a given queryId and timestamp
* @param _queryId the id to look up
* @param _timestamp is the timestamp of the value to look up
* @return address reporter who submitted the value
* @return bool true if the value was removed
*/
function getReportDetails(bytes32 _queryId, uint256 _timestamp)
external
view
returns (address, bool)
{
return (reports[_queryId].reporterByTimestamp[_timestamp], reports[_queryId].isDisputed[_timestamp]);
}
/**
* @dev Returns the address of the reporter who submitted a value for a data ID at a specific time
* @param _queryId is ID of the specific data feed
* @param _timestamp is the timestamp to find a corresponding reporter for
* @return address of the reporter who reported the value for the data ID at the given timestamp
*/
function getReporterByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (address)
{
return reports[_queryId].reporterByTimestamp[_timestamp];
}
/**
* @dev Returns the timestamp of the reporter's last submission
* @param _reporter is address of the reporter
* @return uint256 timestamp of the reporter's last submission
*/
function getReporterLastTimestamp(address _reporter)
external
view
returns (uint256)
{
return stakerDetails[_reporter].reporterLastTimestamp;
}
/**
* @dev Returns the reporting lock time, the amount of time a reporter must wait to submit again
* @return uint256 reporting lock time
*/
function getReportingLock() external view returns (uint256) {
return reportingLock;
}
/**
* @dev Returns the number of values submitted by a specific reporter address
* @param _reporter is the address of a reporter
* @return uint256 the number of values submitted by the given reporter
*/
function getReportsSubmittedByAddress(address _reporter)
external
view
returns (uint256)
{
return stakerDetails[_reporter].reportsSubmitted;
}
/**
* @dev Returns the number of values submitted to a specific queryId by a specific reporter address
* @param _reporter is the address of a reporter
* @param _queryId is the ID of the specific data feed
* @return uint256 the number of values submitted by the given reporter to the given queryId
*/
function getReportsSubmittedByAddressAndQueryId(
address _reporter,
bytes32 _queryId
) external view returns (uint256) {
return stakerDetails[_reporter].reportsSubmittedByQueryId[_queryId];
}
/**
* @dev Returns amount required to report oracle values
* @return uint256 stake amount
*/
function getStakeAmount() external view returns (uint256) {
return stakeAmount;
}
/**
* @dev Returns all information about a staker
* @param _stakerAddress address of staker inquiring about
* @return uint startDate of staking
* @return uint current amount staked
* @return uint current amount locked for withdrawal
* @return uint reward debt used to calculate staking rewards
* @return uint reporter's last reported timestamp
* @return uint total number of reports submitted by reporter
* @return uint governance vote count when first staked
* @return uint number of votes cast by staker when first staked
* @return bool whether staker is counted in totalStakers
*/
function getStakerInfo(address _stakerAddress)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
bool
)
{
StakeInfo storage _staker = stakerDetails[_stakerAddress];
return (
_staker.startDate,
_staker.stakedBalance,
_staker.lockedBalance,
_staker.rewardDebt,
_staker.reporterLastTimestamp,
_staker.reportsSubmitted,
_staker.startVoteCount,
_staker.startVoteTally,
_staker.staked
);
}
/**
* @dev Returns the timestamp for the last value of any ID from the oracle
* @return uint256 timestamp of the last oracle value
*/
function getTimeOfLastNewValue() external view returns (uint256) {
return timeOfLastNewValue;
}
/**
* @dev Gets the timestamp for the value based on their index
* @param _queryId is the id to look up
* @param _index is the value index to look up
* @return uint256 timestamp
*/
function getTimestampbyQueryIdandIndex(bytes32 _queryId, uint256 _index)
public
view
returns (uint256)
{
return reports[_queryId].timestamps[_index];
}
/**
* @dev Retrieves latest array index of data before the specified timestamp for the queryId
* @param _queryId is the queryId to look up the index for
* @param _timestamp is the timestamp before which to search for the latest index
* @return _found whether the index was found
* @return _index the latest index found before the specified timestamp
*/
// slither-disable-next-line calls-loop
function getIndexForDataBefore(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bool _found, uint256 _index)
{
uint256 _count = getNewValueCountbyQueryId(_queryId);
if (_count > 0) {
uint256 _middle;
uint256 _start = 0;
uint256 _end = _count - 1;
uint256 _time;
//Checking Boundaries to short-circuit the algorithm
_time = getTimestampbyQueryIdandIndex(_queryId, _start);
if (_time >= _timestamp) return (false, 0);
_time = getTimestampbyQueryIdandIndex(_queryId, _end);
if (_time < _timestamp) {
while(isInDispute(_queryId, _time) && _end > 0) {
_end--;
_time = getTimestampbyQueryIdandIndex(_queryId, _end);
}
if(_end == 0 && isInDispute(_queryId, _time)) {
return (false, 0);
}
return (true, _end);
}
//Since the value is within our boundaries, do a binary search
while (true) {
_middle = (_end - _start) / 2 + 1 + _start;
_time = getTimestampbyQueryIdandIndex(_queryId, _middle);
if (_time < _timestamp) {
//get immediate next value
uint256 _nextTime = getTimestampbyQueryIdandIndex(
_queryId,
_middle + 1
);
if (_nextTime >= _timestamp) {
if(!isInDispute(_queryId, _time)) {
// _time is correct
return (true, _middle);
} else {
// iterate backwards until we find a non-disputed value
while(isInDispute(_queryId, _time) && _middle > 0) {
_middle--;
_time = getTimestampbyQueryIdandIndex(_queryId, _middle);
}
if(_middle == 0 && isInDispute(_queryId, _time)) {
return (false, 0);
}
// _time is correct
return (true, _middle);
}
} else {
//look from middle + 1(next value) to end
_start = _middle + 1;
}
} else {
uint256 _prevTime = getTimestampbyQueryIdandIndex(
_queryId,
_middle - 1
);
if (_prevTime < _timestamp) {
if(!isInDispute(_queryId, _prevTime)) {
// _prevTime is correct
return (true, _middle - 1);
} else {
// iterate backwards until we find a non-disputed value
_middle--;
while(isInDispute(_queryId, _prevTime) && _middle > 0) {
_middle--;
_prevTime = getTimestampbyQueryIdandIndex(
_queryId,
_middle
);
}
if(_middle == 0 && isInDispute(_queryId, _prevTime)) {
return (false, 0);
}
// _prevtime is correct
return (true, _middle);
}
} else {
//look from start to middle -1(prev value)
_end = _middle - 1;
}
}
}
}
return (false, 0);
}
/**
* @dev Returns the index of a reporter timestamp in the timestamp array for a specific data ID
* @param _queryId is ID of the specific data feed
* @param _timestamp is the timestamp to find in the timestamps array
* @return uint256 of the index of the reporter timestamp in the array for specific ID
*/
function getTimestampIndexByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (uint256)
{
return reports[_queryId].timestampIndex[_timestamp];
}
/**
* @dev Returns the address of the token used for staking
* @return address of the token used for staking
*/
function getTokenAddress() external view returns (address) {
return address(token);
}
/**
* @dev Returns total amount of token staked for reporting
* @return uint256 total amount of token staked
*/
function getTotalStakeAmount() external view returns (uint256) {
return totalStakeAmount;
}
/**
* @dev Returns total number of current stakers. Reporters with stakedBalance less than stakeAmount are excluded from this total
* @return uint256 total stakers
*/
function getTotalStakers() external view returns (uint256) {
return totalStakers;
}
/**
* @dev Returns total balance of time based rewards in contract
* @return uint256 amount of fetch
*/
function getTotalTimeBasedRewardsBalance() external view returns (uint256) {
return token.balanceOf(address(this)) - (totalStakeAmount + stakingRewardsBalance + toWithdraw);
}
/**
* @dev Returns whether a given value is disputed
* @param _queryId unique ID of the data feed
* @param _timestamp timestamp of the value
* @return bool whether the value is disputed
*/
function isInDispute(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bool)
{
return reports[_queryId].isDisputed[_timestamp];
}
/**
* @dev Retrieve value from oracle based on timestamp
* @param _queryId being requested
* @param _timestamp to retrieve data/value from
* @return bytes value for timestamp submitted
*/
function retrieveData(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bytes memory)
{
return reports[_queryId].valueByTimestamp[_timestamp];
}
/**
* @dev Used during the upgrade process to verify valid Fetch contracts
* @return bool value used to verify valid Fetch contracts
*/
function verify() external virtual pure returns (uint256) {
return 8888;
}
// *****************************************************************************
// * *
// * Managed Queries functions *
// * *
// *****************************************************************************
function setupManagedQuery(bytes32 _queryId, address _manager, bytes calldata _config) external onlyOwner {
require(address(_manager) != address(0), "invalid manager address");
require(reports[_queryId].timestamps.length == 0, "cannot setup an existing feed");
queryConfig[_queryId].manager = address(_manager);
// Unwrap the config here
(bool requiresStaking) = abi.decode(_config, (bool));
queryConfig[_queryId].config[keccak256("REQUIRES_STAKING")] = requiresStaking?1:0;
}
function removeManagedQuery(bytes32 _queryId) external onlyOwner {
require(isManagedQuery(_queryId), "not managed query");
require(reports[_queryId].timestamps.length == 0, "cannot remove a feed with data");
queryConfig[_queryId].manager = address(0);
// clears the managedReporters set for the given queryId
while (EnumerableSet.length(managedReporters[_queryId]) > 0) {
EnumerableSet.remove(managedReporters[_queryId], EnumerableSet.at(managedReporters[_queryId], 0));
}
}
function addReporter(bytes32 _queryId, address _reporter) external onlyManager(_queryId) {
require(isManagedQuery(_queryId), "not managed query");
require(address(_reporter) != address(0), "invalid reporter address");
require(!EnumerableSet.contains(managedReporters[_queryId], _reporter), "reporter already included");
EnumerableSet.add(managedReporters[_queryId], _reporter);
}
function removeReporter(bytes32 _queryId, address _reporter) external onlyManager(_queryId) {
require(isManagedQuery(_queryId), "not managed query");
require(address(_reporter) != address(0), "invalid reporter address");
require(EnumerableSet.contains(managedReporters[_queryId], _reporter), "reporter not included");
EnumerableSet.remove(managedReporters[_queryId], _reporter);
}
/**
* @notice Retrieves the manager and reporters for a given query ID
* @dev The manager is returned as the first element in the array, followed by the reporters
* @param _queryId The ID of the query to retrieve the manager and reporters for
* @return address[] An array where the first address is the manager and the subsequent addresses are reporters
*/
function getReporters(bytes32 _queryId) external view returns (address[] memory) {
require(isManagedQuery(_queryId), "not managed query");
address[] memory reporters = new address[](EnumerableSet.length(managedReporters[_queryId]) + 1);
reporters[0] = queryConfig[_queryId].manager;
for (uint i = 0; i < EnumerableSet.length(managedReporters[_queryId]); i++) {
reporters[i+1] = EnumerableSet.at(managedReporters[_queryId], i);
}
return reporters;
}
function isManagedQuery(bytes32 _queryId) public view returns (bool) {
return (queryConfig[_queryId].manager != address(0))? true : false;
}
function isReporterForQuery(bytes32 _queryId, address _reporter) public view returns (bool) {
return EnumerableSet.contains(managedReporters[_queryId], _reporter);
}
function getQueryConfig(bytes32 _queryId) internal view returns (bool) {
require(isManagedQuery(_queryId), "not managed query");
(bool requiresStaking) = queryConfig[_queryId].config[keccak256("REQUIRES_STAKING")] == 1;
return (requiresStaking);
}
// *****************************************************************************
// * *
// * Internal functions *
// * *
// *****************************************************************************
/**
* @dev Updates accumulated staking rewards per staked token
*/
function _updateRewards() internal {
if (timeOfLastAllocation == block.timestamp) {
return;
}
if (totalStakeAmount == 0 || rewardRate == 0) {
timeOfLastAllocation = block.timestamp;
return;
}
// calculate accumulated reward per token staked
uint256 _newAccumulatedRewardPerShare = accumulatedRewardPerShare +
((block.timestamp - timeOfLastAllocation) * rewardRate * 1e18) /
totalStakeAmount;
// calculate accumulated reward with _newAccumulatedRewardPerShare
uint256 _accumulatedReward = (_newAccumulatedRewardPerShare *
totalStakeAmount) /
1e18 -
totalRewardDebt;
if (_accumulatedReward >= stakingRewardsBalance) {
// if staking rewards run out, calculate remaining reward per staked
// token and set rewardRate to 0
uint256 _newPendingRewards = stakingRewardsBalance -
((accumulatedRewardPerShare * totalStakeAmount) /
1e18 -
totalRewardDebt);
accumulatedRewardPerShare +=
(_newPendingRewards * 1e18) /
totalStakeAmount;
rewardRate = 0;
} else {
accumulatedRewardPerShare = _newAccumulatedRewardPerShare;
}
timeOfLastAllocation = block.timestamp;
}
/**
* @dev Called whenever a user's stake amount changes. First updates staking rewards,
* transfers pending rewards to user's address, and finally updates user's stake amount
* and other relevant variables.
* @param _stakerAddress address of user whose stake is being updated
* @param _newStakedBalance new staked balance of user
*/
function _updateStakeAndPayRewards(
address _stakerAddress,
uint256 _newStakedBalance
) internal {
_updateRewards();
StakeInfo storage _staker = stakerDetails[_stakerAddress];
if (_staker.stakedBalance > 0) {
// if address already has a staked balance, calculate and transfer pending rewards
uint256 _pendingReward = (_staker.stakedBalance *
accumulatedRewardPerShare) /
1e18 -
_staker.rewardDebt;
// get staker voting participation rate
uint256 _numberOfVotes;
(bool _success, bytes memory _returnData) = governance.call(
abi.encodeWithSignature("getVoteCount()")
);
if (_success) {
_numberOfVotes =
uint256(abi.decode(_returnData, (uint256))) -
_staker.startVoteCount;
}
if (_numberOfVotes > 0) {
// staking reward = pending reward * voting participation rate
(_success, _returnData) = governance.call(
abi.encodeWithSignature("getVoteTallyByAddress(address)",_stakerAddress)
);
if(_success){
uint256 _voteTally = abi.decode(_returnData,(uint256));
uint256 _tempPendingReward =
(_pendingReward *
(_voteTally - _staker.startVoteTally)) /
_numberOfVotes;
if (_tempPendingReward < _pendingReward) {
_pendingReward = _tempPendingReward;
}
}
}
stakingRewardsBalance -= _pendingReward;
require(token.transfer(_stakerAddress, _pendingReward));
emit StakingRewardTransfer(_stakerAddress, _pendingReward);
totalRewardDebt -= _staker.rewardDebt;
totalStakeAmount -= _staker.stakedBalance;
}
_staker.stakedBalance = _newStakedBalance;
// Update total stakers
if (_staker.stakedBalance >= stakeAmount) {
if (_staker.staked == false) {
totalStakers++;
}
_staker.staked = true;
} else {
if (_staker.staked == true && totalStakers > 0) {
totalStakers--;
}
_staker.staked = false;
}
// tracks rewards accumulated before stake amount updated
_staker.rewardDebt =
(_staker.stakedBalance * accumulatedRewardPerShare) /
1e18;
totalRewardDebt += _staker.rewardDebt;
totalStakeAmount += _staker.stakedBalance;
// update reward rate if staking rewards are available
// given staker's updated parameters
if(rewardRate == 0) {
rewardRate =
(stakingRewardsBalance -
((accumulatedRewardPerShare * totalStakeAmount) /
1e18 -
totalRewardDebt)) /
30 days;
}
}
/**
* @dev Internal function retrieves updated accumulatedRewardPerShare
* @return uint256 up-to-date accumulated reward per share
*/
function _getUpdatedAccumulatedRewardPerShare()
internal
view
returns (uint256)
{
if (totalStakeAmount == 0) {
return accumulatedRewardPerShare;
}
uint256 _newAccumulatedRewardPerShare = accumulatedRewardPerShare +
((block.timestamp - timeOfLastAllocation) * rewardRate * 1e18) /
totalStakeAmount;
uint256 _accumulatedReward = (_newAccumulatedRewardPerShare *
totalStakeAmount) /
1e18 -
totalRewardDebt;
if (_accumulatedReward >= stakingRewardsBalance) {
uint256 _newPendingRewards = stakingRewardsBalance -
((accumulatedRewardPerShare * totalStakeAmount) /
1e18 -
totalRewardDebt);
_newAccumulatedRewardPerShare =
accumulatedRewardPerShare +
(_newPendingRewards * 1e18) /
totalStakeAmount;
}
return _newAccumulatedRewardPerShare;
}
/**Internal Functions */
/**
* @dev Used during the upgrade process to verify valid Fetch Contracts and ensure
* they have the right signature
* @param _contract is the address of the Fetch contract to verify
* @return bool of whether or not the address is a valid Fetch contract
*/
function _isValid(address _contract) internal view returns (bool) {
(bool _success, bytes memory _data) = address(_contract).staticcall(
abi.encodeWithSelector(this.verify.selector, "") // verify() signature
);
require(
_success && abi.decode(_data, (uint256)) > 8887, // An arbitrary number to ensure that the contract is valid
"New contract is invalid"
);
return true;
}
function getTimeBasedReward() internal view returns (uint256) {
uint80[101] memory TIME_BASED_REWARD = [
1425963951631302500000,
1497262149212868000000,
1572125256673511200000,
1650731519507187000000,
1733268095482546200000,
1819931500256673300000,
1910928075269507000000,
2006474479032982200000,
2106798202984631400000,
2212138113133863000000,
2322745018790556400000,
2438882269730084200000,
2560826383216588000000,
2688867702377420000000,
2823311087496292000000,
2964476641871103000000,
3112700473964662500000,
3268335497662895400000,
3431752272546035000000,
3603339886173346300000,
3783506880482009000000,
3972682224506104000000,
4171316335731416500000,
4379882152517985000000,
4598876260143881700000,
4828820073151073300000,
5070261076808630000000,
5323774130649059000000,
5589962837181514000000,
5869460979040600000000,
6162934027992619000000,
6471080729392258000000,
6794634765861871000000,
7134366504154959000000,
7491084829362719000000,
7865639070830861000000,
8258921024372397000000,
8671867075591017000000,
9105460429370556000000,
9560733450839085000000,
10038770123381056000000,
10540708629550105000000,
11067744061027607000000,
11621131264079000000000,
12202187827282930000000,
12812297218647064000000,
13452912079579427000000,
14125557683558434000000,
14831835567736353000000,
15573427346123170000000,
16352098713429316000000,
17169703649100799000000,
18028188831555834000000,
18929598273133587000000,
19876078186790300000000,
20869882096129800000000,
21913376200936310000000,
23009045010983100000000,
24159497261532317000000,
25367472124608860000000,
26635845730839280000000,
27967638017381267000000,
29366019918250376000000,
30834320914162872000000,
32376036959871035000000,
33994838807864618000000,
35694580748257767000000,
37479309785670713000000,
39353275274954257000000,
41320939038701993000000,
43386985990637090000000,
45556335290168960000000,
47834152054677250000000,
50225859657411270000000,
52737152640281880000000,
55374010272295830000000,
58142710785910670000000,
61049846325206230000000,
64102338641466545000000,
67307455573539850000000,
70672828352216890000000,
74206469769827800000000,
77916793258319150000000,
81812632921235100000000,
85903264567296800000000,
90198427795661600000000,
94708349185444820000000,
99443766644716840000000,
104415954976952860000000,
109636752725800500000000,
115118590362090560000000,
120874519880194960000000,
126918245874205030000000,
133264158167915270000000,
139927366076310910000000,
146923734380126330000000,
154269921099132560000000,
161983417154089210000000,
170082588011793600000000,
178586717412383400000000,
187516053283002600000000
];
uint a = (block.timestamp - tokenCreatedAt)/31557600;
uint b = 100;
uint i = a < b ? a : b;
return TIME_BASED_REWARD[i];
}
function timeBasedReward() external view returns (uint256) {
return getTimeBasedReward();
}
}
fetchflex/contracts/dependencies/upgrades/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
fetchflex/contracts/interfaces/IFetchToken.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
interface IFetchToken {
function mintToOracle() external;
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function getCreatedAt() external view returns (uint256);
}
fetchflex/contracts/dependencies/upgrades/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "./Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
fetchflex/contracts/dependencies/upgrades/ERC1967UpgradeUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "./IBeaconUpgradeable.sol";
import "./interfaces/IERC1967Upgradeable.sol";
import "./interfaces/draft-IERC1822Upgradeable.sol";
import "./AddressUpgradeable.sol";
import "./StorageSlotUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
fetchflex/contracts/dependencies/upgrades/IBeaconUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
fetchflex/contracts/dependencies/upgrades/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "./AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
fetchflex/contracts/dependencies/upgrades/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "./ContextUpgradeable.sol";
import "./Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
fetchflex/contracts/dependencies/upgrades/StorageSlotUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
fetchflex/contracts/dependencies/upgrades/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "./interfaces/draft-IERC1822Upgradeable.sol";
import "./ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
fetchflex/contracts/dependencies/upgrades/interfaces/IERC1967Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967Upgradeable {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
fetchflex/contracts/dependencies/upgrades/interfaces/draft-IERC1822Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822ProxiableUpgradeable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
fetchflex/contracts/dependencies/utils/EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity 0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","storageLayout"],"":["ast"]}},"optimizer":{"runs":300,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"NewReport","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32","indexed":true},{"type":"uint256","name":"_time","internalType":"uint256","indexed":true},{"type":"bytes","name":"_value","internalType":"bytes","indexed":false},{"type":"uint256","name":"_nonce","internalType":"uint256","indexed":false},{"type":"bytes","name":"_queryData","internalType":"bytes","indexed":false},{"type":"address","name":"_reporter","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"NewStakeAmount","inputs":[{"type":"uint256","name":"_newStakeAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_stakingTokenPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewStaker","inputs":[{"type":"address","name":"_staker","internalType":"address","indexed":true},{"type":"uint256","name":"_amount","internalType":"uint256","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":"ReporterSlashed","inputs":[{"type":"address","name":"_reporter","internalType":"address","indexed":true},{"type":"address","name":"_recipient","internalType":"address","indexed":false},{"type":"uint256","name":"_slashAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"StakeWithdrawRequested","inputs":[{"type":"address","name":"_staker","internalType":"address","indexed":false},{"type":"uint256","name":"_amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"StakeWithdrawn","inputs":[{"type":"address","name":"_staker","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"StakingRewardTransfer","inputs":[{"type":"address","name":"_reporter","internalType":"address","indexed":true},{"type":"uint256","name":"_reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimeBasedRewardTransfer","inputs":[{"type":"address","name":"_reporter","internalType":"address","indexed":true},{"type":"uint256","name":"_reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ValueRemoved","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"_timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"accumulatedRewardPerShare","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addReporter","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"address","name":"_reporter","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addStakingRewards","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"depositStake","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBlockNumberByTimestamp","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"_value","internalType":"bytes"}],"name":"getCurrentValue","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_ifRetrieve","internalType":"bool"},{"type":"bytes","name":"_value","internalType":"bytes"},{"type":"uint256","name":"_timestampRetrieved","internalType":"uint256"}],"name":"getDataBefore","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getGovernanceAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_found","internalType":"bool"},{"type":"uint256","name":"_index","internalType":"uint256"}],"name":"getIndexForDataBefore","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNewValueCountbyQueryId","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_pendingReward","internalType":"uint256"}],"name":"getPendingRewardByStaker","inputs":[{"type":"address","name":"_stakerAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRealStakingRewardsBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"bool","name":"","internalType":"bool"}],"name":"getReportDetails","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getReporterByTimestamp","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getReporterLastTimestamp","inputs":[{"type":"address","name":"_reporter","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getReporters","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getReportingLock","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getReportsSubmittedByAddress","inputs":[{"type":"address","name":"_reporter","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getReportsSubmittedByAddressAndQueryId","inputs":[{"type":"address","name":"_reporter","internalType":"address"},{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"}],"name":"getStakerInfo","inputs":[{"type":"address","name":"_stakerAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTimeOfLastNewValue","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTimestampIndexByTimestamp","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTimestampbyQueryIdandIndex","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getTokenAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalStakers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalTimeBasedRewardsBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[{"type":"address","name":"_governanceAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_token","internalType":"address"},{"type":"uint256","name":"_reportingLock","internalType":"uint256"},{"type":"uint256","name":"_stakeAmountDollarTarget","internalType":"uint256"},{"type":"uint256","name":"_stakingTokenPrice","internalType":"uint256"},{"type":"uint256","name":"_minimumStakeAmount","internalType":"uint256"},{"type":"bytes32","name":"_stakingTokenPriceQueryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isInDispute","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isManagedQuery","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isReporterForQuery","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"address","name":"_reporter","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minimumStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeManagedQuery","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeReporter","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"address","name":"_reporter","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeValue","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reportingLock","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"requestStakingWithdraw","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"retrieveData","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardRate","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setupManagedQuery","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"address","name":"_manager","internalType":"address"},{"type":"bytes","name":"_config","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_slashAmount","internalType":"uint256"}],"name":"slashReporter","inputs":[{"type":"address","name":"_reporter","internalType":"address"},{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stakeAmountDollarTarget","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stakingRewardsBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"stakingTokenPriceQueryId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submitValue","inputs":[{"type":"bytes32","name":"_queryId","internalType":"bytes32"},{"type":"bytes","name":"_value","internalType":"bytes"},{"type":"uint256","name":"_nonce","internalType":"uint256"},{"type":"bytes","name":"_queryData","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeBasedReward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeOfLastAllocation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeOfLastDistribution","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeOfLastNewValue","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"toWithdraw","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFetchToken"}],"name":"token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenCreatedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardDebt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStakers","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateStakeAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"verify","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawStake","inputs":[]}]
Contract Creation Code
0x60a06040523060805234801562000014575f80fd5b506200001f62000025565b620000e3565b5f54610100900460ff1615620000915760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000e1575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615509620001185f395f818161115e0152818161119e015281816117120152818161175201526117df01526155095ff3fe6080604052600436106103df575f3560e01c806373e9e80c116101ff578063bf5745d611610113578063cf21f0e3116100a8578063ec972fb011610078578063ec972fb014610c74578063f2fde38b14610c8a578063fc0c546a14610ca9578063fc735e9914610cc8578063fd0b69af14610cdc575f80fd5b8063cf21f0e314610bdf578063d75174e114610bfe578063d9c51cd414610c12578063e07c548614610c31575f80fd5b8063cb82cc8f116100e3578063cb82cc8f14610b77578063cbc0f3a114610b96578063ce5e11bf14610bab578063cecb064714610bca575f80fd5b8063bf5745d614610b10578063c0d416b814610b2f578063c0f95d5214610b44578063c5958af914610b58575f80fd5b806392d6c5b7116101945780639d9b16ed116101645780639d9b16ed14610a49578063a792765f14610a83578063ab4d2d1c14610ab1578063adf1639d14610ad0578063bed9d86114610afc575f80fd5b806392d6c5b7146109c7578063935408d0146109e657806394409a5614610a2057806396426d9714610a35575f80fd5b806386989038116101cf578063869890381461095757806386cb625e1461096c5780638929f4c61461098b5780638da5cb5b146109aa575f80fd5b806373e9e80c146108d657806377b03e0d146109025780637b0a47ee1461092d57806383bb387714610942575f80fd5b80634c565046116102f657806360c7dc471161028b5780636fd4f2291161025b5780636fd4f229146107c5578063715018a6146107da578063722580b6146107ee5780637325249414610802578063733bdef01461081f575f80fd5b806360c7dc47146107685780636378daae1461077d5780636b036f451461079c5780636dd0a70f146107b1575f80fd5b806352d1902d116102c657806352d1902d146106f75780635aa6e6751461070b5780635b5edcfc1461072a5780635eaa9ced14610749575f80fd5b80634c5650461461066f5780634dfc2a341461068e5780634f1ef286146106ad57806350005b83146106c0575f80fd5b806331ed0db41161037757806336d421951161034757806336d42195146105ae5780633878293e146105c35780633a0ce342146105fa57806344e87f911461060e578063460c33a21461065b575f80fd5b806331ed0db4146105515780633321fc4114610565578063347f23361461057a5780633659cfe61461058f575f80fd5b806319ab453c116103b257806319ab453c1461046f57806329449085146104905780632b6696a7146104c65780632e206cd71461053c575f80fd5b806304d932e2146103e357806310fe9ae81461040b57806311938e081461043c57806314c2a1bc1461045b575b5f80fd5b3480156103ee575f80fd5b506103f860d15481565b6040519081526020015b60405180910390f35b348015610416575f80fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610402565b348015610447575f80fd5b506103f8610456366004614c43565b610cfb565b348015610466575f80fd5b5060d6546103f8565b34801561047a575f80fd5b5061048e610489366004614c6b565b610d28565b005b34801561049b575f80fd5b506104af6104aa366004614c84565b610e17565b604080519215158352602083019190915201610402565b3480156104d1575f80fd5b5061051d6104e0366004614c84565b5f91825260da60209081526040808420928452600483018252808420546005909301909152909120546001600160a01b039091169160ff90911690565b604080516001600160a01b039093168352901515602083015201610402565b348015610547575f80fd5b506103f860d35481565b34801561055c575f80fd5b5060d7546103f8565b348015610570575f80fd5b506103f860cd5481565b348015610585575f80fd5b506103f860d85481565b34801561059a575f80fd5b5061048e6105a9366004614c6b565b611154565b3480156105b9575f80fd5b506103f860cb5481565b3480156105ce575f80fd5b506103f86105dd366004614c6b565b6001600160a01b03165f90815260db602052604090206005015490565b348015610605575f80fd5b5061048e611231565b348015610619575f80fd5b5061064b610628366004614c84565b5f91825260da602090815260408084209284526005909201905290205460ff1690565b6040519015158152602001610402565b348015610666575f80fd5b5060cd546103f8565b34801561067a575f80fd5b5061048e610689366004614ca4565b611355565b348015610699575f80fd5b506103f86106a8366004614cce565b611493565b61048e6106bb366004614d0a565b611708565b3480156106cb575f80fd5b506103f86106da366004614c6b565b6001600160a01b03165f90815260db602052604090206004015490565b348015610702575f80fd5b506103f86117d3565b348015610716575f80fd5b5060ca54610424906001600160a01b031681565b348015610735575f80fd5b5061048e610744366004614c84565b611884565b348015610754575f80fd5b5061048e610763366004614e04565b611aba565b348015610773575f80fd5b506103f860cf5481565b348015610788575f80fd5b5061064b610797366004614ca4565b612258565b3480156107a7575f80fd5b506103f860cc5481565b3480156107bc575f80fd5b506103f8612276565b3480156107d0575f80fd5b506103f860d45481565b3480156107e5575f80fd5b5061048e612284565b3480156107f9575f80fd5b5060cf546103f8565b34801561080d575f80fd5b5060ca546001600160a01b0316610424565b34801561082a575f80fd5b50610890610839366004614c6b565b6001600160a01b03165f90815260db6020526040902080546001820154600283015460038401546004850154600586015460068701546007880154600890980154969895979496939592949193909260ff90911690565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e0830152151561010082015261012001610402565b3480156108e1575f80fd5b506108f56108f0366004614e81565b612297565b6040516104029190614e98565b34801561090d575f80fd5b506103f861091c366004614e81565b5f90815260da602052604090205490565b348015610938575f80fd5b506103f860ce5481565b34801561094d575f80fd5b506103f860d55481565b348015610962575f80fd5b506103f860d75481565b348015610977575f80fd5b5061048e610986366004614ee4565b612414565b348015610996575f80fd5b5061048e6109a5366004614e81565b612747565b3480156109b5575f80fd5b506033546001600160a01b0316610424565b3480156109d2575f80fd5b5061048e6109e1366004614f2a565b612830565b3480156109f1575f80fd5b506103f8610a00366004614c84565b5f91825260da602090815260408084209284526002909201905290205490565b348015610a2b575f80fd5b506103f860d65481565b348015610a40575f80fd5b506103f8612975565b348015610a54575f80fd5b506103f8610a63366004614c84565b5f91825260da602090815260408084209284526001909201905290205490565b348015610a8e575f80fd5b50610aa2610a9d366004614c84565b61297e565b60405161040293929190614fcd565b348015610abc575f80fd5b5061048e610acb366004614e81565b6129db565b348015610adb575f80fd5b50610aef610aea366004614e81565b612ae6565b6040516104029190614ff7565b348015610b07575f80fd5b5061048e612b0c565b348015610b1b575f80fd5b506103f8610b2a366004614c6b565b612ca2565b348015610b3a575f80fd5b506103f860d05481565b348015610b4f575f80fd5b5060d4546103f8565b348015610b63575f80fd5b50610aef610b72366004614c84565b612ea0565b348015610b82575f80fd5b5061048e610b91366004614e81565b612f4e565b348015610ba1575f80fd5b506103f860d95481565b348015610bb6575f80fd5b506103f8610bc5366004614c84565b6132eb565b348015610bd5575f80fd5b506103f860d25481565b348015610bea575f80fd5b5061048e610bf9366004614ca4565b61331b565b348015610c09575f80fd5b506103f8613452565b348015610c1d575f80fd5b5061048e610c2c366004614e81565b6134e4565b348015610c3c575f80fd5b50610424610c4b366004614c84565b5f91825260da60209081526040808420928452600490920190529020546001600160a01b031690565b348015610c7f575f80fd5b506103f861011d5481565b348015610c95575f80fd5b5061048e610ca4366004614c6b565b6135d5565b348015610cb4575f80fd5b5060c954610424906001600160a01b031681565b348015610cd3575f80fd5b506122b86103f8565b348015610ce7575f80fd5b5061064b610cf6366004614e81565b61364b565b6001600160a01b0382165f90815260db602090815260408083208484526009019091529020545b92915050565b610d30613674565b60ca546001600160a01b031615610d8e5760405162461bcd60e51b815260206004820152601e60248201527f676f7665726e616e6365206164647265737320616c726561647920736574000060448201526064015b60405180910390fd5b6001600160a01b038116610df55760405162461bcd60e51b815260206004820152602860248201527f676f7665726e616e636520616464726573732063616e2774206265207a65726f604482015267206164647265737360c01b6064820152608401610d85565b60ca80546001600160a01b0319166001600160a01b0392909216919091179055565b5f82815260da602052604081205481908015611145575f8080610e3b60018561501d565b90505f610e4889846132eb565b9050878110610e61575f8096509650505050505061114d565b610e6b89836132eb565b905087811015610f11575b5f89815260da6020908152604080832084845260050190915290205460ff168015610ea057505f82115b15610ec35781610eaf81615030565b925050610ebc89836132eb565b9050610e76565b81158015610eec57505f89815260da6020908152604080832084845260050190915290205460ff165b15610f01575f8096509650505050505061114d565b5060019550935061114d92505050565b826002610f1e828561501d565b610f289190615045565b610f33906001615064565b610f3d9190615064565b9350610f4989856132eb565b905087811015611052575f610f638a610bc5876001615064565b905088811061103f575f8a815260da6020908152604080832085845260050190915290205460ff16610fa1576001859750975050505050505061114d565b5f8a815260da6020908152604080832085845260050190915290205460ff168015610fcb57505f85115b15610fee5784610fda81615030565b955050610fe78a866132eb565b9150610fa1565b8415801561101757505f8a815260da6020908152604080832085845260050190915290205460ff165b1561102d575f809750975050505050505061114d565b6001859750975050505050505061114d565b61104a856001615064565b935050610f11565b5f6110628a610bc560018861501d565b905088811015611132575f8a815260da6020908152604080832084845260050190915290205460ff166110aa57600161109b818761501d565b9750975050505050505061114d565b846110b481615030565b9550505b5f8a815260da6020908152604080832084845260050190915290205460ff1680156110e257505f85115b1561110557846110f181615030565b9550506110fe8a866132eb565b90506110b8565b8415801561101757505f8a815260da6020908152604080832084845260050190915290205460ff16611017565b61113d60018661501d565b925050610f11565b5f8092509250505b9250929050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361119c5760405162461bcd60e51b8152600401610d8590615077565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111e45f8051602061548d833981519152546001600160a01b031690565b6001600160a01b03161461120a5760405162461bcd60e51b8152600401610d85906150c3565b611213816136ce565b604080515f8082526020820190925261122e9183919061372b565b50565b5f8061124760d25461a8c042610a9d919061501d565b50915091508115611351575f81806020019051810190611267919061510f565b9050633b9aca008110158015611286575069d3c21bcecceda100000081105b6112d25760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964207374616b696e6720746f6b656e20707269636500000000006044820152606401610d85565b5f8160d054670de0b6b3a76400006112ea9190615126565b6112f49190615045565b905060cc5481101561130b5760cc5460cf55611311565b60cf8190555b60cf5460408051918252602082018490527fa6765b312ad1b9ba850b208d47d411843f41753cc1efbc5bca4f16d5c382050d91015b60405180910390a150505b5050565b5f82815260dc602052604090205482906001600160a01b03163314611378575f80fd5b6113818361364b565b6113c15760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b6001600160a01b0382166114125760405162461bcd60e51b8152602060048201526018602482015277696e76616c6964207265706f72746572206164647265737360401b6044820152606401610d85565b5f83815260dd60205260409020611429908361389a565b156114765760405162461bcd60e51b815260206004820152601960248201527f7265706f7274657220616c726561647920696e636c75646564000000000000006044820152606401610d85565b5f83815260dd6020526040902061148d90836138bb565b50505050565b60ca545f906001600160a01b031633146114fa5760405162461bcd60e51b815260206004820152602260248201527f6f6e6c7920676f7665726e616e63652063616e20736c617368207265706f727460448201526132b960f11b6064820152608401610d85565b6001600160a01b0383165f90815260db6020526040812060018101546002820154919290919061152a8284615064565b1161156d5760405162461bcd60e51b81526020600482015260136024820152727a65726f207374616b65722062616c616e636560681b6044820152606401610d85565b60cf5481106115b45760cf54935060cf54836002015f828254611590919061501d565b909155505060cf5460d880545f906115a990849061501d565b9091555061163d9050565b60cf546115c18383615064565b106116095760cf5493506115e8866115d9838761501d565b6115e3908561501d565b6138cf565b8060d85f8282546115f9919061501d565b90915550505f600284015561163d565b6116138183615064565b93508060d85f828254611626919061501d565b909155506116369050865f6138cf565b5f60028401555b60c95460405163a9059cbb60e01b81526001600160a01b038781166004830152602482018790529091169063a9059cbb906044016020604051808303815f875af115801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b1919061514a565b6116b9575f80fd5b604080516001600160a01b038781168252602082018790528816917f4317784407a22e643706ef000f5c0eea399dea3632613786167ab71c9446e3ac910160405180910390a250505092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036117505760405162461bcd60e51b8152600401610d8590615077565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166117985f8051602061548d833981519152546001600160a01b031690565b6001600160a01b0316146117be5760405162461bcd60e51b8152600401610d85906150c3565b6117c7826136ce565b6113518282600161372b565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118725760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d85565b505f8051602061548d83398151915290565b61188d8261364b565b156118fb5761189c8233612258565b6118f65760405162461bcd60e51b815260206004820152602560248201527f63616c6c6572206d75737420626520616e20617574686f72697a65642072657060448201526437b93a32b960d91b6064820152608401610d85565b61195f565b60ca546001600160a01b0316331461195f5760405162461bcd60e51b815260206004820152602160248201527f63616c6c6572206d75737420626520676f7665726e616e6365206164647265736044820152607360f81b6064820152608401610d85565b5f82815260da60209081526040808320848452600581019092529091205460ff16156119cd5760405162461bcd60e51b815260206004820152601660248201527f76616c756520616c7265616479206469737075746564000000000000000000006044820152606401610d85565b5f82815260018201602052604090205481548290829081106119f1576119f1615165565b905f5260205f2001548314611a3c5760405162461bcd60e51b81526020600482015260116024820152700696e76616c69642074696d657374616d7607c1b6044820152606401610d85565b60408051602080820183525f808352868152600386019091529190912090611a6490826151f8565b505f83815260058301602052604090819020805460ff19166001179055517fb326db0e54476c677e2b35b75856ac6f4d8bbfb0a6de6690582ebe4dabce0de7906113469086908690918252602082015260400190565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708585604051611aeb9291906152b4565b604051809103902003611b405760405162461bcd60e51b815260206004820152601760248201527f76616c7565206d757374206265207375626d69747465640000000000000000006044820152606401610d85565b5f611b4a8761364b565b90505f81611b59576001611b9a565b5f88815260dc602090815260408083207fa75bfa4ccdcbc4df295a00b308b84db1b49e51191218afc254a90fe7645b0ff48452600190810190925290912054145b90508115611bf857611bac8833612258565b611bf85760405162461bcd60e51b815260206004820152601760248201527f7265706f72746572206e6f7420617574686f72697a65640000000000000000006044820152606401610d85565b8115611c4e575f611c0b87890189614e81565b90505f8111611c4c5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b6044820152606401610d85565b505b5f88815260da602052604090208054861480611c68575085155b611cb45760405162461bcd60e51b815260206004820181905260248201527f6e6f6e6365206d757374206d617463682074696d657374616d7020696e6465786044820152606401610d85565b335f90815260db602052604090208215611dd55760cf5481600101541015611d305760405162461bcd60e51b815260206004820152602960248201527f62616c616e6365206d7573742062652067726561746572207468616e207374616044820152681ad948185b5bdd5b9d60ba1b6064820152608401610d85565b60cf548160010154611d429190615045565b60cd54611d51906103e8615126565b611d5b9190615045565b6004820154611d6a904261501d565b611d76906103e8615126565b11611dd55760405162461bcd60e51b815260206004820152602960248201527f7374696c6c20696e207265706f727465722074696d65206c6f636b2c20706c6560448201526861736520776169742160b81b6064820152608401610d85565b8585604051611de59291906152b4565b60405180910390208a14611e475760405162461bcd60e51b815260206004820152602360248201527f7175657279206964206d7573742062652068617368206f66207175657279206460448201526261746160e81b6064820152608401610d85565b4260048083018290555f918252830160205260409020546001600160a01b031615611eb45760405162461bcd60e51b815260206004820152601e60248201527f74696d657374616d7020616c7265616479207265706f7274656420666f7200006044820152606401610d85565b8154425f8181526001808601602090815260408084208690559185018755868352808320909401839055918152600285018352818120439055600385019092529020611f01898b836152c3565b50425f908152600483016020526040902080546001600160a01b0319163317905582156121c75760c95f9054906101000a90046001600160a01b03166001600160a01b031663b67f8cbd6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611f74575f80fd5b505af1158015611f86573d5f803e3d5ffd5b505050505f61012c611f96613d2a565b61011d54611fa4904261501d565b611fae9190615126565b611fb89190615045565b90505f60d85460d15460d654611fce9190615064565b611fd89190615064565b60c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561201e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612042919061510f565b61204c919061501d565b90505f8111801561205c57505f82115b156121bf57818110156121165760c95460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af11580156120b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120db919061514a565b5060405181815233907f4715be7e0ce44cfbdce3afca21d6e8733c4ab3b6b4ec03889852f2533c793ebc9060200160405180910390a26121bf565b60c95460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015612164573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612188919061514a565b5060405182815233907f4715be7e0ce44cfbdce3afca21d6e8733c4ab3b6b4ec03889852f2533c793ebc9060200160405180910390a25b50504261011d555b4260d455600581018054905f6121dc8361537f565b90915550505f8a815260098201602052604081208054916121fc8361537f565b9190505550336001600160a01b0316428b7f48e9e2c732ba278de6ac88a3a57a5c5ba13d3d8370e709b3b98333a57876ca958c8c8c8c8c6040516122449594939291906153bf565b60405180910390a450505050505050505050565b5f82815260dd6020526040812061226f908361389a565b9392505050565b5f61227f61442c565b905090565b61228c613674565b6122955f614479565b565b60606122a28261364b565b6122e25760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b5f82815260dd602052604081206122f8906144ca565b612303906001615064565b67ffffffffffffffff81111561231b5761231b614cf6565b604051908082528060200260200182016040528015612344578160200160208202803683370190505b505f84815260dc602052604081205482519293506001600160a01b03169183919061237157612371615165565b60200260200101906001600160a01b031690816001600160a01b0316815250505f5b5f84815260dd602052604090206123a9906144ca565b81101561240d575f84815260dd602052604090206123c790826144d3565b826123d3836001615064565b815181106123e3576123e3615165565b6001600160a01b0390921660209283029190910190910152806124058161537f565b915050612393565b5092915050565b5f54610100900460ff161580801561243257505f54600160ff909116105b8061244b5750303b15801561244b57505f5460ff166001145b6124ae5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d85565b5f805460ff1916600117905580156124cf575f805461ff0019166101001790555b6124d76144de565b6001600160a01b03871661252d5760405162461bcd60e51b815260206004820152601660248201527f6d7573742073657420746f6b656e2061646472657373000000000000000000006044820152606401610d85565b5f841161257c5760405162461bcd60e51b815260206004820152601c60248201527f6d75737420736574207374616b696e6720746f6b656e207072696365000000006044820152606401610d85565b5f86116125cb5760405162461bcd60e51b815260206004820152601760248201527f6d75737420736574207265706f7274696e67206c6f636b0000000000000000006044820152606401610d85565b816126245760405162461bcd60e51b8152602060048201526024808201527f6d75737420736574207374616b696e6720746f6b656e207072696365207175656044820152631c9e525960e21b6064820152608401610d85565b4260d481905561011d5560c980546001600160a01b0319166001600160a01b03891690811790915560408051630fc0beb560e31b81529051637e05f5a8916004808201926020929091908290030181865afa158015612685573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a9919061510f565b60d95560cd86905560d085905560cc8390555f846126cf87670de0b6b3a7640000615126565b6126d99190615045565b9050838110156126ed5760cf8490556126f3565b60cf8190555b5060d2829055801561273e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b335f90815260db6020526040902060018101548211156127a95760405162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e74207374616b65642062616c616e636500000000006044820152606401610d85565b6127bd338383600101546115e3919061501d565b4281556002810180548391905f906127d6908490615064565b925050819055508160d85f8282546127ee9190615064565b909155505060408051338152602081018490527f3d8d9df4bd0172df32e557fa48e96435cd7f2cac06aaffacfaee608e6f7898ef910160405180910390a15050565b612838613674565b6001600160a01b03831661288e5760405162461bcd60e51b815260206004820152601760248201527f696e76616c6964206d616e6167657220616464726573730000000000000000006044820152606401610d85565b5f84815260da6020526040902054156128e95760405162461bcd60e51b815260206004820152601d60248201527f63616e6e6f7420736574757020616e206578697374696e6720666565640000006044820152606401610d85565b5f84815260dc6020526040812080546001600160a01b0319166001600160a01b03861617905561291b838301846153f7565b905080612928575f61292b565b60015b5f95865260dc602090815260408088207fa75bfa4ccdcbc4df295a00b308b84db1b49e51191218afc254a90fe7645b0ff4895260010190915290952060ff90951690945550505050565b5f61227f613d2a565b5f60605f805f61298e8787610e17565b91509150816129b5575f60405180602001604052805f8152505f94509450945050506129d4565b6129bf87826132eb565b92506129cb8784612ea0565b93506001945050505b9250925092565b6129e3613674565b6129ec8161364b565b612a2c5760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b5f81815260da602052604090205415612a875760405162461bcd60e51b815260206004820152601e60248201527f63616e6e6f742072656d6f7665206120666565642077697468206461746100006044820152606401610d85565b5f81815260dc6020526040902080546001600160a01b03191690555b5f81815260dd60205260408120612ab9906144ca565b111561122e575f81815260dd60205260408120612ae091612adb9082906144d3565b61450c565b50612aa3565b60605f612af883610a9d426001615064565b509250905080612b06575f80fd5b50919050565b335f90815260db60205260409020805462093a8090612b2b904261501d565b1015612b6e5760405162461bcd60e51b8152602060048201526012602482015271372064617973206469646e2774207061737360701b6044820152606401610d85565b5f816002015411612bcc5760405162461bcd60e51b815260206004820152602260248201527f7265706f72746572206e6f74206c6f636b656420666f72207769746864726177604482015261185b60f21b6064820152608401610d85565b60c954600282015460405163a9059cbb60e01b815233600482015260248101919091526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015612c20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c44919061514a565b612c4c575f80fd5b806002015460d85f828254612c61919061501d565b90915550505f60028201556040513381527f4a7934670bd8304e7da22378be1368f7c4fef17c5aee81804beda8638fe428ec9060200160405180910390a150565b6001600160a01b0381165f90815260db602052604081206003810154670de0b6b3a7640000612ccf614520565b8360010154612cde9190615126565b612ce89190615045565b612cf2919061501d565b60ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290519294505f9283926001600160a01b031691612d3991615412565b5f60405180830381855afa9150503d805f8114612d71576040519150601f19603f3d011682016040523d82523d5f602084013e612d76565b606091505b50915091505f8215612da857836006015482806020019051810190612d9b919061510f565b612da5919061501d565b90505b8015612e975760ca546040516001600160a01b0388811660248301529091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b17905251612e009190615412565b5f60405180830381855afa9150503d805f8114612e38576040519150601f19603f3d011682016040523d82523d5f602084013e612e3d565b606091505b5090935091508215612e97575f82806020019051810190612e5e919061510f565b90505f82866007015483612e72919061501d565b612e7c9089615126565b612e869190615045565b905086811015612e94578096505b50505b50505050919050565b5f82815260da602090815260408083208484526003019091529020805460609190612eca90615179565b80601f0160208091040260200160405190810160405280929190818152602001828054612ef690615179565b8015612f415780601f10612f1857610100808354040283529160200191612f41565b820191905f5260205f20905b815481529060010190602001808311612f2457829003601f168201915b5050505050905092915050565b60ca546001600160a01b0316612fa65760405162461bcd60e51b815260206004820152601a60248201527f676f7665726e616e63652061646472657373206e6f74207365740000000000006044820152606401610d85565b335f90815260db602052604090206001810154600282015480156130c0578381106130015783836002015f828254612fde919061501d565b925050819055508360d85f828254612ff6919061501d565b909155506132a89050565b60c9546001600160a01b03166323b872dd333061301e858961501d565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303815f875af115801561306f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613093919061514a565b61309b575f80fd5b826002015460d85f8282546130b0919061501d565b90915550505f60028401556132a8565b815f036132285760ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290515f9283926001600160a01b039091169161310e9190615412565b5f604051808303815f865af19150503d805f8114613147576040519150601f19603f3d011682016040523d82523d5f602084013e61314c565b606091505b50915091508115613171578080602001905181019061316b919061510f565b60068601555b60ca546040513360248201526001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b179052516131c19190615412565b5f604051808303815f865af19150503d805f81146131fa576040519150601f19603f3d011682016040523d82523d5f602084013e6131ff565b606091505b5090925090508115613225578080602001905181019061321f919061510f565b60078601555b50505b60c9546040516323b872dd60e01b8152336004820152306024820152604481018690526001600160a01b03909116906323b872dd906064016020604051808303815f875af115801561327c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132a0919061514a565b6132a8575f80fd5b6132b6336115e38685615064565b428355604051849033907fa96c2cce65119a2170d1711a6e82f18f2006448828483ba7545e595476543647905f90a350505050565b5f82815260da6020526040812080548390811061330a5761330a615165565b905f5260205f200154905092915050565b5f82815260dc602052604090205482906001600160a01b0316331461333e575f80fd5b6133478361364b565b6133875760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b6001600160a01b0382166133d85760405162461bcd60e51b8152602060048201526018602482015277696e76616c6964207265706f72746572206164647265737360401b6044820152606401610d85565b5f83815260dd602052604090206133ef908361389a565b61343b5760405162461bcd60e51b815260206004820152601560248201527f7265706f72746572206e6f7420696e636c7564656400000000000000000000006044820152606401610d85565b5f83815260dd6020526040902061148d908361450c565b5f60d85460d15460d6546134669190615064565b6134709190615064565b60c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156134b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134da919061510f565b61227f919061501d565b60c9546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015613538573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061355c919061514a565b613564575f80fd5b61356c61462a565b8060d15f82825461357d9190615064565b9250508190555062278d0060d554670de0b6b3a764000060d65460cb546135a49190615126565b6135ae9190615045565b6135b8919061501d565b60d1546135c5919061501d565b6135cf9190615045565b60ce5550565b6135dd613674565b6001600160a01b0381166136425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d85565b61122e81614479565b5f81815260dc60205260408120546001600160a01b031661366c575f610d22565b600192915050565b6033546001600160a01b031633146122955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d85565b6136d6613674565b6136df81614760565b61122e5760405162461bcd60e51b815260206004820152601660248201527f696e76616c6964206f7261636c652061646472657373000000000000000000006044820152606401610d85565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156137635761375e83614886565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156137bd575060408051601f3d908101601f191682019092526137ba9181019061510f565b60015b6138205760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d85565b5f8051602061548d833981519152811461388e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d85565b5061375e838383614921565b6001600160a01b0381165f908152600183016020526040812054151561226f565b5f61226f836001600160a01b038416614945565b6138d761462a565b6001600160a01b0382165f90815260db60205260409020600181015415613be7575f8160030154670de0b6b3a764000060cb5484600101546139199190615126565b6139239190615045565b61392d919061501d565b60ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290519293505f92839283926001600160a01b03909116916139799190615412565b5f604051808303815f865af19150503d805f81146139b2576040519150601f19603f3d011682016040523d82523d5f602084013e6139b7565b606091505b509150915081156139e8578460060154818060200190518101906139db919061510f565b6139e5919061501d565b92505b8215613ad85760ca546040516001600160a01b0389811660248301529091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b17905251613a409190615412565b5f604051808303815f865af19150503d805f8114613a79576040519150601f19603f3d011682016040523d82523d5f602084013e613a7e565b606091505b5090925090508115613ad8575f81806020019051810190613a9f919061510f565b90505f84876007015483613ab3919061501d565b613abd9088615126565b613ac79190615045565b905085811015613ad5578095505b50505b8360d15f828254613ae9919061501d565b909155505060c95460405163a9059cbb60e01b81526001600160a01b038981166004830152602482018790529091169063a9059cbb906044016020604051808303815f875af1158015613b3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b62919061514a565b613b6a575f80fd5b866001600160a01b03167fe88340f53b0d013ca3a9592feb1a168ed82ebda01019fa89303cb64068251c1285604051613ba591815260200190565b60405180910390a2846003015460d55f828254613bc2919061501d565b9091555050600185015460d680545f90613bdd90849061501d565b9091555050505050505b6001810182905560cf548210613c3057600881015460ff1615155f03613c1c5760d78054905f613c168361537f565b91905055505b60088101805460ff19166001179055613c71565b600881015460ff1615156001148015613c4a57505f60d754115b15613c645760d78054905f613c5e83615030565b91905055505b60088101805460ff191690555b670de0b6b3a764000060cb548260010154613c8c9190615126565b613c969190615045565b6003820181905560d580545f90613cae908490615064565b9091555050600181015460d680545f90613cc9908490615064565b909155505060ce545f0361375e5762278d0060d554670de0b6b3a764000060d65460cb54613cf79190615126565b613d019190615045565b613d0b919061501d565b60d154613d18919061501d565b613d229190615045565b60ce55505050565b60408051610ca081018252684d4d39a2ed88159ea0815268512aafb7dfcee9390060208201526855399ee777cc71d5009181019190915268597c80730a96ae62c06060820152685df5ed4597eb019dc060808201526862a89f8912b6be7e2060a0820152686797744fed3fe226c060c0820152686cc56d53ec4fde5ec060e0820152687235b2cb51ba4476406101008201526877eb95557c36c857c0610120820152687dea900028d322f9806101408201526884364a669144179e40610160820152688ad29aebb221128b006101808201526891c3891114a2e18b006101a082015268990d4feb88de48e1006101c082015268a0b460b74fb5fbfdc06101e082015268a8bd658d46e5be2aa061020082015268b12d443abda46aa44061022082015268ba09213dad85ede2c061024082015268c35662e72966cb806061026082015268cd1ab4a5eb7875a84061028082015268d75c0a7b040af52e006102a082015268e220a49ac43f2407206102c082015268ed6f133c1adbc25a406102e082015268f94e3a98b5ccfec2a0610300820152690105c55720587d7f2e20610320820152690112dc01e1f683f3d9806103408201526901209a352d42d7337ec061036082015269012f08516f862ee2268061038082015269013e2f224eb34b7106006103a082015269014e17e405d5db5ba0c06103c082015269015ecc4906208d34a4806103e0820152690170567fe008944599c0610400820152690182c139780901c131c061042082015269019617af8ad6428f85c06104408201526901aa65ab84fa930c9d406104608201526901bfb78db20719fb45406104808201526901d61a54c7baa816ec406104a08201526901ed9ba5d1b72fc9a7006104c082015269020649d48299f23fa5406104e082015269022033ebef880c28d00061050082015269023b69b7bb820c8a7840610520820152690257fbcdb81559c633c0610540820152690275fb9801499f0456006105608201526902957b5f9af3b29360806105808201526902b68e5795e6478f36006105a08201526902d948a8c3cb65524ec06105c08201526902fdbf7e00c8c61ccc806105e082015269032409111a6c69750a4061060082015269034c3cb85bbea1e42c8061062082015269037672f4c6bb5c70d9006106408201526903a2c58103de5549bdc06106608201526903d14f6110dca60eb2806106808201526904022cf2b81adf40eac06106a08201526904357bfedae906059f006106c082015269046b5bcb990e456dd2006106e08201526904a3ed2f60b563b149806107008201526904df52a4f2580d8ea70061072082015269051db06064dc7854a14061074082015269055f2c6536b446ce0f006107608201526905a3ee9d79707c2c9c006107808201526905ec20f225e9508dcac06107a0820152690637ef64a7ce974d72006107c08201526906878829b03283e89e006107e08201526906db1bc55f683edc44c0610800820152690732dd28d760aa441e8061082082015269078f01d1488be11907c06108408201526907efc1e88c2c7c96c04061086082015269085558675ffb8350e6406108808201526908c0033957fb4b42fc406108a082015269093003629c6175444c806108c08201526909a59d278a9988daa0006108e0820152690a211836518793144480610900820152690aa2bfd2a267fd6bbd80610920820152690b2ae30390ed33437600610940820152690bb9d4c3be92a0719180610960820152690c4fec33ee805e8e7f80610980820152690ced84d020d3981061806109a0820152690d92fea755aaf979ce406109c0820152690e40be9619f3849f96806109e0820152690ef72e8401a61ae2c280610a00820152690fb6bda434ee6cef2600610a2082015269107fe0b93793efff2780610a40820152691153125c13f4eebfdf00610a60820152691230d34714f45dcf0800610a80820152691319aaa43c66f9b70800610aa082015269140e265fa5d28e8b9d00610ac082015269150edb7e07b6a2199a00610ae082015269161c667788196803bf00610b008201526917376b971bb446a2f500610b20820152691860975ea9e3b2a79000610b408201526919989ef0326240c20400610b60820152691ae0407c34e73d96a580610b80820152691c3843b59df2ccc84d80610ba0820152691da17a4b7f721c75db80610bc0820152691f1cc068df6afccd9280610be08201526920aafd3aea96b77cc400610c0082015269224d237ddcb7db92b280610c208201526924043210f48dd58cb000610c408201526925d13491cd94f42dfa00610c608201526927b543ff7e42cefa0a00610c8082015260d9545f919082906301e187e0906143e0904261501d565b6143ea9190615045565b905060645f8183106143fc57816143fe565b825b905083816065811061441257614412615165565b602002015169ffffffffffffffffffff1694505050505090565b5f8060d554670de0b6b3a764000060d654614445614520565b61444f9190615126565b6144599190615045565b614463919061501d565b90508060d154614473919061501d565b91505090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f610d22825490565b5f61226f8383614991565b5f54610100900460ff166145045760405162461bcd60e51b8152600401610d859061542d565b6122956149a6565b5f61226f836001600160a01b0384166149d5565b5f60d6545f03614531575060cb5490565b5f60d65460ce5460d35442614546919061501d565b6145509190615126565b61456290670de0b6b3a7640000615126565b61456c9190615045565b60cb546145799190615064565b90505f60d554670de0b6b3a764000060d654846145969190615126565b6145a09190615045565b6145aa919061501d565b905060d1548110612b06575f60d554670de0b6b3a764000060d65460cb546145d29190615126565b6145dc9190615045565b6145e6919061501d565b60d1546145f3919061501d565b60d65490915061460b82670de0b6b3a7640000615126565b6146159190615045565b60cb546146229190615064565b949350505050565b4260d3540361463557565b60d6541580614644575060ce54155b1561464f574260d355565b5f60d65460ce5460d35442614664919061501d565b61466e9190615126565b61468090670de0b6b3a7640000615126565b61468a9190615045565b60cb546146979190615064565b90505f60d554670de0b6b3a764000060d654846146b49190615126565b6146be9190615045565b6146c8919061501d565b905060d1548110614752575f60d554670de0b6b3a764000060d65460cb546146f09190615126565b6146fa9190615045565b614704919061501d565b60d154614711919061501d565b60d65490915061472982670de0b6b3a7640000615126565b6147339190615045565b60cb5f8282546147439190615064565b90915550505f60ce5550614758565b60cb8290555b50504260d355565b5f805f836001600160a01b031663fc735e9960e01b60405160240161478f9060208082525f9082015260400190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516147cd9190615412565b5f60405180830381855afa9150503d805f8114614805576040519150601f19603f3d011682016040523d82523d5f602084013e61480a565b606091505b509150915081801561483057506122b78180602001905181019061482e919061510f565b115b61487c5760405162461bcd60e51b815260206004820152601760248201527f4e657720636f6e747261637420697320696e76616c69640000000000000000006044820152606401610d85565b5060019392505050565b6001600160a01b0381163b6148f35760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d85565b5f8051602061548d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61492a83614ab8565b5f825111806149365750805b1561375e5761148d8383614af7565b5f81815260018301602052604081205461498a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610d22565b505f610d22565b5f825f01828154811061330a5761330a615165565b5f54610100900460ff166149cc5760405162461bcd60e51b8152600401610d859061542d565b61229533614479565b5f8181526001830160205260408120548015614aaf575f6149f760018361501d565b85549091505f90614a0a9060019061501d565b9050808214614a69575f865f018281548110614a2857614a28615165565b905f5260205f200154905080875f018481548110614a4857614a48615165565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080614a7a57614a7a615478565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610d22565b5f915050610d22565b614ac181614886565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b606061226f83836040518060600160405280602781526020016154ad6027913960605f80856001600160a01b031685604051614b339190615412565b5f60405180830381855af49150503d805f8114614b6b576040519150601f19603f3d011682016040523d82523d5f602084013e614b70565b606091505b5091509150614b8186838387614b8b565b9695505050505050565b60608315614bf95782515f03614bf2576001600160a01b0385163b614bf25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d85565b5081614622565b6146228383815115614c0e5781518083602001fd5b8060405162461bcd60e51b8152600401610d859190614ff7565b80356001600160a01b0381168114614c3e575f80fd5b919050565b5f8060408385031215614c54575f80fd5b614c5d83614c28565b946020939093013593505050565b5f60208284031215614c7b575f80fd5b61226f82614c28565b5f8060408385031215614c95575f80fd5b50508035926020909101359150565b5f8060408385031215614cb5575f80fd5b82359150614cc560208401614c28565b90509250929050565b5f8060408385031215614cdf575f80fd5b614ce883614c28565b9150614cc560208401614c28565b634e487b7160e01b5f52604160045260245ffd5b5f8060408385031215614d1b575f80fd5b614d2483614c28565b9150602083013567ffffffffffffffff80821115614d40575f80fd5b818501915085601f830112614d53575f80fd5b813581811115614d6557614d65614cf6565b604051601f8201601f19908116603f01168101908382118183101715614d8d57614d8d614cf6565b81604052828152886020848701011115614da5575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f8083601f840112614dd6575f80fd5b50813567ffffffffffffffff811115614ded575f80fd5b60208301915083602082850101111561114d575f80fd5b5f805f805f8060808789031215614e19575f80fd5b86359550602087013567ffffffffffffffff80821115614e37575f80fd5b614e438a838b01614dc6565b9097509550604089013594506060890135915080821115614e62575f80fd5b50614e6f89828a01614dc6565b979a9699509497509295939492505050565b5f60208284031215614e91575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015614ed85783516001600160a01b031683529284019291840191600101614eb3565b50909695505050505050565b5f805f805f8060c08789031215614ef9575f80fd5b614f0287614c28565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b5f805f8060608587031215614f3d575f80fd5b84359350614f4d60208601614c28565b9250604085013567ffffffffffffffff811115614f68575f80fd5b614f7487828801614dc6565b95989497509550505050565b5f5b83811015614f9a578181015183820152602001614f82565b50505f910152565b5f8151808452614fb9816020860160208601614f80565b601f01601f19169290920160200192915050565b8315158152606060208201525f614fe76060830185614fa2565b9050826040830152949350505050565b602081525f61226f6020830184614fa2565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d2257610d22615009565b5f8161503e5761503e615009565b505f190190565b5f8261505f57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d2257610d22615009565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f6020828403121561511f575f80fd5b5051919050565b8082028115828204841417610d2257610d22615009565b801515811461122e575f80fd5b5f6020828403121561515a575f80fd5b815161226f8161513d565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061518d57607f821691505b602082108103612b0657634e487b7160e01b5f52602260045260245ffd5b601f82111561375e575f81815260208120601f850160051c810160208610156151d15750805b601f850160051c820191505b818110156151f0578281556001016151dd565b505050505050565b815167ffffffffffffffff81111561521257615212614cf6565b615226816152208454615179565b846151ab565b602080601f831160018114615259575f84156152425750858301515b5f19600386901b1c1916600185901b1785556151f0565b5f85815260208120601f198616915b8281101561528757888601518255948401946001909101908401615268565b50858210156152a457878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b818382375f9101908152919050565b67ffffffffffffffff8311156152db576152db614cf6565b6152ef836152e98354615179565b836151ab565b5f601f841160018114615320575f85156153095750838201355b5f19600387901b1c1916600186901b178355615378565b5f83815260209020601f19861690835b828110156153505786850135825560209485019460019092019101615330565b508682101561536c575f1960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b5f6001820161539057615390615009565b5060010190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b606081525f6153d2606083018789615397565b85602084015282810360408401526153eb818587615397565b98975050505050505050565b5f60208284031215615407575f80fd5b813561226f8161513d565b5f8251615423818460208701614f80565b9190910192915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b5f52603160045260245ffdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122032447ae98509ab4e45c964753eb29eb87099951f0fccdd08fb100c368c7db06264736f6c63430008140033
Deployed ByteCode
0x6080604052600436106103df575f3560e01c806373e9e80c116101ff578063bf5745d611610113578063cf21f0e3116100a8578063ec972fb011610078578063ec972fb014610c74578063f2fde38b14610c8a578063fc0c546a14610ca9578063fc735e9914610cc8578063fd0b69af14610cdc575f80fd5b8063cf21f0e314610bdf578063d75174e114610bfe578063d9c51cd414610c12578063e07c548614610c31575f80fd5b8063cb82cc8f116100e3578063cb82cc8f14610b77578063cbc0f3a114610b96578063ce5e11bf14610bab578063cecb064714610bca575f80fd5b8063bf5745d614610b10578063c0d416b814610b2f578063c0f95d5214610b44578063c5958af914610b58575f80fd5b806392d6c5b7116101945780639d9b16ed116101645780639d9b16ed14610a49578063a792765f14610a83578063ab4d2d1c14610ab1578063adf1639d14610ad0578063bed9d86114610afc575f80fd5b806392d6c5b7146109c7578063935408d0146109e657806394409a5614610a2057806396426d9714610a35575f80fd5b806386989038116101cf578063869890381461095757806386cb625e1461096c5780638929f4c61461098b5780638da5cb5b146109aa575f80fd5b806373e9e80c146108d657806377b03e0d146109025780637b0a47ee1461092d57806383bb387714610942575f80fd5b80634c565046116102f657806360c7dc471161028b5780636fd4f2291161025b5780636fd4f229146107c5578063715018a6146107da578063722580b6146107ee5780637325249414610802578063733bdef01461081f575f80fd5b806360c7dc47146107685780636378daae1461077d5780636b036f451461079c5780636dd0a70f146107b1575f80fd5b806352d1902d116102c657806352d1902d146106f75780635aa6e6751461070b5780635b5edcfc1461072a5780635eaa9ced14610749575f80fd5b80634c5650461461066f5780634dfc2a341461068e5780634f1ef286146106ad57806350005b83146106c0575f80fd5b806331ed0db41161037757806336d421951161034757806336d42195146105ae5780633878293e146105c35780633a0ce342146105fa57806344e87f911461060e578063460c33a21461065b575f80fd5b806331ed0db4146105515780633321fc4114610565578063347f23361461057a5780633659cfe61461058f575f80fd5b806319ab453c116103b257806319ab453c1461046f57806329449085146104905780632b6696a7146104c65780632e206cd71461053c575f80fd5b806304d932e2146103e357806310fe9ae81461040b57806311938e081461043c57806314c2a1bc1461045b575b5f80fd5b3480156103ee575f80fd5b506103f860d15481565b6040519081526020015b60405180910390f35b348015610416575f80fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610402565b348015610447575f80fd5b506103f8610456366004614c43565b610cfb565b348015610466575f80fd5b5060d6546103f8565b34801561047a575f80fd5b5061048e610489366004614c6b565b610d28565b005b34801561049b575f80fd5b506104af6104aa366004614c84565b610e17565b604080519215158352602083019190915201610402565b3480156104d1575f80fd5b5061051d6104e0366004614c84565b5f91825260da60209081526040808420928452600483018252808420546005909301909152909120546001600160a01b039091169160ff90911690565b604080516001600160a01b039093168352901515602083015201610402565b348015610547575f80fd5b506103f860d35481565b34801561055c575f80fd5b5060d7546103f8565b348015610570575f80fd5b506103f860cd5481565b348015610585575f80fd5b506103f860d85481565b34801561059a575f80fd5b5061048e6105a9366004614c6b565b611154565b3480156105b9575f80fd5b506103f860cb5481565b3480156105ce575f80fd5b506103f86105dd366004614c6b565b6001600160a01b03165f90815260db602052604090206005015490565b348015610605575f80fd5b5061048e611231565b348015610619575f80fd5b5061064b610628366004614c84565b5f91825260da602090815260408084209284526005909201905290205460ff1690565b6040519015158152602001610402565b348015610666575f80fd5b5060cd546103f8565b34801561067a575f80fd5b5061048e610689366004614ca4565b611355565b348015610699575f80fd5b506103f86106a8366004614cce565b611493565b61048e6106bb366004614d0a565b611708565b3480156106cb575f80fd5b506103f86106da366004614c6b565b6001600160a01b03165f90815260db602052604090206004015490565b348015610702575f80fd5b506103f86117d3565b348015610716575f80fd5b5060ca54610424906001600160a01b031681565b348015610735575f80fd5b5061048e610744366004614c84565b611884565b348015610754575f80fd5b5061048e610763366004614e04565b611aba565b348015610773575f80fd5b506103f860cf5481565b348015610788575f80fd5b5061064b610797366004614ca4565b612258565b3480156107a7575f80fd5b506103f860cc5481565b3480156107bc575f80fd5b506103f8612276565b3480156107d0575f80fd5b506103f860d45481565b3480156107e5575f80fd5b5061048e612284565b3480156107f9575f80fd5b5060cf546103f8565b34801561080d575f80fd5b5060ca546001600160a01b0316610424565b34801561082a575f80fd5b50610890610839366004614c6b565b6001600160a01b03165f90815260db6020526040902080546001820154600283015460038401546004850154600586015460068701546007880154600890980154969895979496939592949193909260ff90911690565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e0830152151561010082015261012001610402565b3480156108e1575f80fd5b506108f56108f0366004614e81565b612297565b6040516104029190614e98565b34801561090d575f80fd5b506103f861091c366004614e81565b5f90815260da602052604090205490565b348015610938575f80fd5b506103f860ce5481565b34801561094d575f80fd5b506103f860d55481565b348015610962575f80fd5b506103f860d75481565b348015610977575f80fd5b5061048e610986366004614ee4565b612414565b348015610996575f80fd5b5061048e6109a5366004614e81565b612747565b3480156109b5575f80fd5b506033546001600160a01b0316610424565b3480156109d2575f80fd5b5061048e6109e1366004614f2a565b612830565b3480156109f1575f80fd5b506103f8610a00366004614c84565b5f91825260da602090815260408084209284526002909201905290205490565b348015610a2b575f80fd5b506103f860d65481565b348015610a40575f80fd5b506103f8612975565b348015610a54575f80fd5b506103f8610a63366004614c84565b5f91825260da602090815260408084209284526001909201905290205490565b348015610a8e575f80fd5b50610aa2610a9d366004614c84565b61297e565b60405161040293929190614fcd565b348015610abc575f80fd5b5061048e610acb366004614e81565b6129db565b348015610adb575f80fd5b50610aef610aea366004614e81565b612ae6565b6040516104029190614ff7565b348015610b07575f80fd5b5061048e612b0c565b348015610b1b575f80fd5b506103f8610b2a366004614c6b565b612ca2565b348015610b3a575f80fd5b506103f860d05481565b348015610b4f575f80fd5b5060d4546103f8565b348015610b63575f80fd5b50610aef610b72366004614c84565b612ea0565b348015610b82575f80fd5b5061048e610b91366004614e81565b612f4e565b348015610ba1575f80fd5b506103f860d95481565b348015610bb6575f80fd5b506103f8610bc5366004614c84565b6132eb565b348015610bd5575f80fd5b506103f860d25481565b348015610bea575f80fd5b5061048e610bf9366004614ca4565b61331b565b348015610c09575f80fd5b506103f8613452565b348015610c1d575f80fd5b5061048e610c2c366004614e81565b6134e4565b348015610c3c575f80fd5b50610424610c4b366004614c84565b5f91825260da60209081526040808420928452600490920190529020546001600160a01b031690565b348015610c7f575f80fd5b506103f861011d5481565b348015610c95575f80fd5b5061048e610ca4366004614c6b565b6135d5565b348015610cb4575f80fd5b5060c954610424906001600160a01b031681565b348015610cd3575f80fd5b506122b86103f8565b348015610ce7575f80fd5b5061064b610cf6366004614e81565b61364b565b6001600160a01b0382165f90815260db602090815260408083208484526009019091529020545b92915050565b610d30613674565b60ca546001600160a01b031615610d8e5760405162461bcd60e51b815260206004820152601e60248201527f676f7665726e616e6365206164647265737320616c726561647920736574000060448201526064015b60405180910390fd5b6001600160a01b038116610df55760405162461bcd60e51b815260206004820152602860248201527f676f7665726e616e636520616464726573732063616e2774206265207a65726f604482015267206164647265737360c01b6064820152608401610d85565b60ca80546001600160a01b0319166001600160a01b0392909216919091179055565b5f82815260da602052604081205481908015611145575f8080610e3b60018561501d565b90505f610e4889846132eb565b9050878110610e61575f8096509650505050505061114d565b610e6b89836132eb565b905087811015610f11575b5f89815260da6020908152604080832084845260050190915290205460ff168015610ea057505f82115b15610ec35781610eaf81615030565b925050610ebc89836132eb565b9050610e76565b81158015610eec57505f89815260da6020908152604080832084845260050190915290205460ff165b15610f01575f8096509650505050505061114d565b5060019550935061114d92505050565b826002610f1e828561501d565b610f289190615045565b610f33906001615064565b610f3d9190615064565b9350610f4989856132eb565b905087811015611052575f610f638a610bc5876001615064565b905088811061103f575f8a815260da6020908152604080832085845260050190915290205460ff16610fa1576001859750975050505050505061114d565b5f8a815260da6020908152604080832085845260050190915290205460ff168015610fcb57505f85115b15610fee5784610fda81615030565b955050610fe78a866132eb565b9150610fa1565b8415801561101757505f8a815260da6020908152604080832085845260050190915290205460ff165b1561102d575f809750975050505050505061114d565b6001859750975050505050505061114d565b61104a856001615064565b935050610f11565b5f6110628a610bc560018861501d565b905088811015611132575f8a815260da6020908152604080832084845260050190915290205460ff166110aa57600161109b818761501d565b9750975050505050505061114d565b846110b481615030565b9550505b5f8a815260da6020908152604080832084845260050190915290205460ff1680156110e257505f85115b1561110557846110f181615030565b9550506110fe8a866132eb565b90506110b8565b8415801561101757505f8a815260da6020908152604080832084845260050190915290205460ff16611017565b61113d60018661501d565b925050610f11565b5f8092509250505b9250929050565b6001600160a01b037f000000000000000000000000890f129ac1df3094641414723052a194980fea4016300361119c5760405162461bcd60e51b8152600401610d8590615077565b7f000000000000000000000000890f129ac1df3094641414723052a194980fea406001600160a01b03166111e45f8051602061548d833981519152546001600160a01b031690565b6001600160a01b03161461120a5760405162461bcd60e51b8152600401610d85906150c3565b611213816136ce565b604080515f8082526020820190925261122e9183919061372b565b50565b5f8061124760d25461a8c042610a9d919061501d565b50915091508115611351575f81806020019051810190611267919061510f565b9050633b9aca008110158015611286575069d3c21bcecceda100000081105b6112d25760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964207374616b696e6720746f6b656e20707269636500000000006044820152606401610d85565b5f8160d054670de0b6b3a76400006112ea9190615126565b6112f49190615045565b905060cc5481101561130b5760cc5460cf55611311565b60cf8190555b60cf5460408051918252602082018490527fa6765b312ad1b9ba850b208d47d411843f41753cc1efbc5bca4f16d5c382050d91015b60405180910390a150505b5050565b5f82815260dc602052604090205482906001600160a01b03163314611378575f80fd5b6113818361364b565b6113c15760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b6001600160a01b0382166114125760405162461bcd60e51b8152602060048201526018602482015277696e76616c6964207265706f72746572206164647265737360401b6044820152606401610d85565b5f83815260dd60205260409020611429908361389a565b156114765760405162461bcd60e51b815260206004820152601960248201527f7265706f7274657220616c726561647920696e636c75646564000000000000006044820152606401610d85565b5f83815260dd6020526040902061148d90836138bb565b50505050565b60ca545f906001600160a01b031633146114fa5760405162461bcd60e51b815260206004820152602260248201527f6f6e6c7920676f7665726e616e63652063616e20736c617368207265706f727460448201526132b960f11b6064820152608401610d85565b6001600160a01b0383165f90815260db6020526040812060018101546002820154919290919061152a8284615064565b1161156d5760405162461bcd60e51b81526020600482015260136024820152727a65726f207374616b65722062616c616e636560681b6044820152606401610d85565b60cf5481106115b45760cf54935060cf54836002015f828254611590919061501d565b909155505060cf5460d880545f906115a990849061501d565b9091555061163d9050565b60cf546115c18383615064565b106116095760cf5493506115e8866115d9838761501d565b6115e3908561501d565b6138cf565b8060d85f8282546115f9919061501d565b90915550505f600284015561163d565b6116138183615064565b93508060d85f828254611626919061501d565b909155506116369050865f6138cf565b5f60028401555b60c95460405163a9059cbb60e01b81526001600160a01b038781166004830152602482018790529091169063a9059cbb906044016020604051808303815f875af115801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b1919061514a565b6116b9575f80fd5b604080516001600160a01b038781168252602082018790528816917f4317784407a22e643706ef000f5c0eea399dea3632613786167ab71c9446e3ac910160405180910390a250505092915050565b6001600160a01b037f000000000000000000000000890f129ac1df3094641414723052a194980fea401630036117505760405162461bcd60e51b8152600401610d8590615077565b7f000000000000000000000000890f129ac1df3094641414723052a194980fea406001600160a01b03166117985f8051602061548d833981519152546001600160a01b031690565b6001600160a01b0316146117be5760405162461bcd60e51b8152600401610d85906150c3565b6117c7826136ce565b6113518282600161372b565b5f306001600160a01b037f000000000000000000000000890f129ac1df3094641414723052a194980fea4016146118725760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d85565b505f8051602061548d83398151915290565b61188d8261364b565b156118fb5761189c8233612258565b6118f65760405162461bcd60e51b815260206004820152602560248201527f63616c6c6572206d75737420626520616e20617574686f72697a65642072657060448201526437b93a32b960d91b6064820152608401610d85565b61195f565b60ca546001600160a01b0316331461195f5760405162461bcd60e51b815260206004820152602160248201527f63616c6c6572206d75737420626520676f7665726e616e6365206164647265736044820152607360f81b6064820152608401610d85565b5f82815260da60209081526040808320848452600581019092529091205460ff16156119cd5760405162461bcd60e51b815260206004820152601660248201527f76616c756520616c7265616479206469737075746564000000000000000000006044820152606401610d85565b5f82815260018201602052604090205481548290829081106119f1576119f1615165565b905f5260205f2001548314611a3c5760405162461bcd60e51b81526020600482015260116024820152700696e76616c69642074696d657374616d7607c1b6044820152606401610d85565b60408051602080820183525f808352868152600386019091529190912090611a6490826151f8565b505f83815260058301602052604090819020805460ff19166001179055517fb326db0e54476c677e2b35b75856ac6f4d8bbfb0a6de6690582ebe4dabce0de7906113469086908690918252602082015260400190565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708585604051611aeb9291906152b4565b604051809103902003611b405760405162461bcd60e51b815260206004820152601760248201527f76616c7565206d757374206265207375626d69747465640000000000000000006044820152606401610d85565b5f611b4a8761364b565b90505f81611b59576001611b9a565b5f88815260dc602090815260408083207fa75bfa4ccdcbc4df295a00b308b84db1b49e51191218afc254a90fe7645b0ff48452600190810190925290912054145b90508115611bf857611bac8833612258565b611bf85760405162461bcd60e51b815260206004820152601760248201527f7265706f72746572206e6f7420617574686f72697a65640000000000000000006044820152606401610d85565b8115611c4e575f611c0b87890189614e81565b90505f8111611c4c5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b6044820152606401610d85565b505b5f88815260da602052604090208054861480611c68575085155b611cb45760405162461bcd60e51b815260206004820181905260248201527f6e6f6e6365206d757374206d617463682074696d657374616d7020696e6465786044820152606401610d85565b335f90815260db602052604090208215611dd55760cf5481600101541015611d305760405162461bcd60e51b815260206004820152602960248201527f62616c616e6365206d7573742062652067726561746572207468616e207374616044820152681ad948185b5bdd5b9d60ba1b6064820152608401610d85565b60cf548160010154611d429190615045565b60cd54611d51906103e8615126565b611d5b9190615045565b6004820154611d6a904261501d565b611d76906103e8615126565b11611dd55760405162461bcd60e51b815260206004820152602960248201527f7374696c6c20696e207265706f727465722074696d65206c6f636b2c20706c6560448201526861736520776169742160b81b6064820152608401610d85565b8585604051611de59291906152b4565b60405180910390208a14611e475760405162461bcd60e51b815260206004820152602360248201527f7175657279206964206d7573742062652068617368206f66207175657279206460448201526261746160e81b6064820152608401610d85565b4260048083018290555f918252830160205260409020546001600160a01b031615611eb45760405162461bcd60e51b815260206004820152601e60248201527f74696d657374616d7020616c7265616479207265706f7274656420666f7200006044820152606401610d85565b8154425f8181526001808601602090815260408084208690559185018755868352808320909401839055918152600285018352818120439055600385019092529020611f01898b836152c3565b50425f908152600483016020526040902080546001600160a01b0319163317905582156121c75760c95f9054906101000a90046001600160a01b03166001600160a01b031663b67f8cbd6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611f74575f80fd5b505af1158015611f86573d5f803e3d5ffd5b505050505f61012c611f96613d2a565b61011d54611fa4904261501d565b611fae9190615126565b611fb89190615045565b90505f60d85460d15460d654611fce9190615064565b611fd89190615064565b60c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561201e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612042919061510f565b61204c919061501d565b90505f8111801561205c57505f82115b156121bf57818110156121165760c95460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af11580156120b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120db919061514a565b5060405181815233907f4715be7e0ce44cfbdce3afca21d6e8733c4ab3b6b4ec03889852f2533c793ebc9060200160405180910390a26121bf565b60c95460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015612164573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612188919061514a565b5060405182815233907f4715be7e0ce44cfbdce3afca21d6e8733c4ab3b6b4ec03889852f2533c793ebc9060200160405180910390a25b50504261011d555b4260d455600581018054905f6121dc8361537f565b90915550505f8a815260098201602052604081208054916121fc8361537f565b9190505550336001600160a01b0316428b7f48e9e2c732ba278de6ac88a3a57a5c5ba13d3d8370e709b3b98333a57876ca958c8c8c8c8c6040516122449594939291906153bf565b60405180910390a450505050505050505050565b5f82815260dd6020526040812061226f908361389a565b9392505050565b5f61227f61442c565b905090565b61228c613674565b6122955f614479565b565b60606122a28261364b565b6122e25760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b5f82815260dd602052604081206122f8906144ca565b612303906001615064565b67ffffffffffffffff81111561231b5761231b614cf6565b604051908082528060200260200182016040528015612344578160200160208202803683370190505b505f84815260dc602052604081205482519293506001600160a01b03169183919061237157612371615165565b60200260200101906001600160a01b031690816001600160a01b0316815250505f5b5f84815260dd602052604090206123a9906144ca565b81101561240d575f84815260dd602052604090206123c790826144d3565b826123d3836001615064565b815181106123e3576123e3615165565b6001600160a01b0390921660209283029190910190910152806124058161537f565b915050612393565b5092915050565b5f54610100900460ff161580801561243257505f54600160ff909116105b8061244b5750303b15801561244b57505f5460ff166001145b6124ae5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d85565b5f805460ff1916600117905580156124cf575f805461ff0019166101001790555b6124d76144de565b6001600160a01b03871661252d5760405162461bcd60e51b815260206004820152601660248201527f6d7573742073657420746f6b656e2061646472657373000000000000000000006044820152606401610d85565b5f841161257c5760405162461bcd60e51b815260206004820152601c60248201527f6d75737420736574207374616b696e6720746f6b656e207072696365000000006044820152606401610d85565b5f86116125cb5760405162461bcd60e51b815260206004820152601760248201527f6d75737420736574207265706f7274696e67206c6f636b0000000000000000006044820152606401610d85565b816126245760405162461bcd60e51b8152602060048201526024808201527f6d75737420736574207374616b696e6720746f6b656e207072696365207175656044820152631c9e525960e21b6064820152608401610d85565b4260d481905561011d5560c980546001600160a01b0319166001600160a01b03891690811790915560408051630fc0beb560e31b81529051637e05f5a8916004808201926020929091908290030181865afa158015612685573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a9919061510f565b60d95560cd86905560d085905560cc8390555f846126cf87670de0b6b3a7640000615126565b6126d99190615045565b9050838110156126ed5760cf8490556126f3565b60cf8190555b5060d2829055801561273e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b335f90815260db6020526040902060018101548211156127a95760405162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e74207374616b65642062616c616e636500000000006044820152606401610d85565b6127bd338383600101546115e3919061501d565b4281556002810180548391905f906127d6908490615064565b925050819055508160d85f8282546127ee9190615064565b909155505060408051338152602081018490527f3d8d9df4bd0172df32e557fa48e96435cd7f2cac06aaffacfaee608e6f7898ef910160405180910390a15050565b612838613674565b6001600160a01b03831661288e5760405162461bcd60e51b815260206004820152601760248201527f696e76616c6964206d616e6167657220616464726573730000000000000000006044820152606401610d85565b5f84815260da6020526040902054156128e95760405162461bcd60e51b815260206004820152601d60248201527f63616e6e6f7420736574757020616e206578697374696e6720666565640000006044820152606401610d85565b5f84815260dc6020526040812080546001600160a01b0319166001600160a01b03861617905561291b838301846153f7565b905080612928575f61292b565b60015b5f95865260dc602090815260408088207fa75bfa4ccdcbc4df295a00b308b84db1b49e51191218afc254a90fe7645b0ff4895260010190915290952060ff90951690945550505050565b5f61227f613d2a565b5f60605f805f61298e8787610e17565b91509150816129b5575f60405180602001604052805f8152505f94509450945050506129d4565b6129bf87826132eb565b92506129cb8784612ea0565b93506001945050505b9250925092565b6129e3613674565b6129ec8161364b565b612a2c5760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b5f81815260da602052604090205415612a875760405162461bcd60e51b815260206004820152601e60248201527f63616e6e6f742072656d6f7665206120666565642077697468206461746100006044820152606401610d85565b5f81815260dc6020526040902080546001600160a01b03191690555b5f81815260dd60205260408120612ab9906144ca565b111561122e575f81815260dd60205260408120612ae091612adb9082906144d3565b61450c565b50612aa3565b60605f612af883610a9d426001615064565b509250905080612b06575f80fd5b50919050565b335f90815260db60205260409020805462093a8090612b2b904261501d565b1015612b6e5760405162461bcd60e51b8152602060048201526012602482015271372064617973206469646e2774207061737360701b6044820152606401610d85565b5f816002015411612bcc5760405162461bcd60e51b815260206004820152602260248201527f7265706f72746572206e6f74206c6f636b656420666f72207769746864726177604482015261185b60f21b6064820152608401610d85565b60c954600282015460405163a9059cbb60e01b815233600482015260248101919091526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015612c20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c44919061514a565b612c4c575f80fd5b806002015460d85f828254612c61919061501d565b90915550505f60028201556040513381527f4a7934670bd8304e7da22378be1368f7c4fef17c5aee81804beda8638fe428ec9060200160405180910390a150565b6001600160a01b0381165f90815260db602052604081206003810154670de0b6b3a7640000612ccf614520565b8360010154612cde9190615126565b612ce89190615045565b612cf2919061501d565b60ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290519294505f9283926001600160a01b031691612d3991615412565b5f60405180830381855afa9150503d805f8114612d71576040519150601f19603f3d011682016040523d82523d5f602084013e612d76565b606091505b50915091505f8215612da857836006015482806020019051810190612d9b919061510f565b612da5919061501d565b90505b8015612e975760ca546040516001600160a01b0388811660248301529091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b17905251612e009190615412565b5f60405180830381855afa9150503d805f8114612e38576040519150601f19603f3d011682016040523d82523d5f602084013e612e3d565b606091505b5090935091508215612e97575f82806020019051810190612e5e919061510f565b90505f82866007015483612e72919061501d565b612e7c9089615126565b612e869190615045565b905086811015612e94578096505b50505b50505050919050565b5f82815260da602090815260408083208484526003019091529020805460609190612eca90615179565b80601f0160208091040260200160405190810160405280929190818152602001828054612ef690615179565b8015612f415780601f10612f1857610100808354040283529160200191612f41565b820191905f5260205f20905b815481529060010190602001808311612f2457829003601f168201915b5050505050905092915050565b60ca546001600160a01b0316612fa65760405162461bcd60e51b815260206004820152601a60248201527f676f7665726e616e63652061646472657373206e6f74207365740000000000006044820152606401610d85565b335f90815260db602052604090206001810154600282015480156130c0578381106130015783836002015f828254612fde919061501d565b925050819055508360d85f828254612ff6919061501d565b909155506132a89050565b60c9546001600160a01b03166323b872dd333061301e858961501d565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303815f875af115801561306f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613093919061514a565b61309b575f80fd5b826002015460d85f8282546130b0919061501d565b90915550505f60028401556132a8565b815f036132285760ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290515f9283926001600160a01b039091169161310e9190615412565b5f604051808303815f865af19150503d805f8114613147576040519150601f19603f3d011682016040523d82523d5f602084013e61314c565b606091505b50915091508115613171578080602001905181019061316b919061510f565b60068601555b60ca546040513360248201526001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b179052516131c19190615412565b5f604051808303815f865af19150503d805f81146131fa576040519150601f19603f3d011682016040523d82523d5f602084013e6131ff565b606091505b5090925090508115613225578080602001905181019061321f919061510f565b60078601555b50505b60c9546040516323b872dd60e01b8152336004820152306024820152604481018690526001600160a01b03909116906323b872dd906064016020604051808303815f875af115801561327c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132a0919061514a565b6132a8575f80fd5b6132b6336115e38685615064565b428355604051849033907fa96c2cce65119a2170d1711a6e82f18f2006448828483ba7545e595476543647905f90a350505050565b5f82815260da6020526040812080548390811061330a5761330a615165565b905f5260205f200154905092915050565b5f82815260dc602052604090205482906001600160a01b0316331461333e575f80fd5b6133478361364b565b6133875760405162461bcd60e51b81526020600482015260116024820152706e6f74206d616e6167656420717565727960781b6044820152606401610d85565b6001600160a01b0382166133d85760405162461bcd60e51b8152602060048201526018602482015277696e76616c6964207265706f72746572206164647265737360401b6044820152606401610d85565b5f83815260dd602052604090206133ef908361389a565b61343b5760405162461bcd60e51b815260206004820152601560248201527f7265706f72746572206e6f7420696e636c7564656400000000000000000000006044820152606401610d85565b5f83815260dd6020526040902061148d908361450c565b5f60d85460d15460d6546134669190615064565b6134709190615064565b60c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156134b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134da919061510f565b61227f919061501d565b60c9546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015613538573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061355c919061514a565b613564575f80fd5b61356c61462a565b8060d15f82825461357d9190615064565b9250508190555062278d0060d554670de0b6b3a764000060d65460cb546135a49190615126565b6135ae9190615045565b6135b8919061501d565b60d1546135c5919061501d565b6135cf9190615045565b60ce5550565b6135dd613674565b6001600160a01b0381166136425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d85565b61122e81614479565b5f81815260dc60205260408120546001600160a01b031661366c575f610d22565b600192915050565b6033546001600160a01b031633146122955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d85565b6136d6613674565b6136df81614760565b61122e5760405162461bcd60e51b815260206004820152601660248201527f696e76616c6964206f7261636c652061646472657373000000000000000000006044820152606401610d85565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156137635761375e83614886565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156137bd575060408051601f3d908101601f191682019092526137ba9181019061510f565b60015b6138205760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d85565b5f8051602061548d833981519152811461388e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d85565b5061375e838383614921565b6001600160a01b0381165f908152600183016020526040812054151561226f565b5f61226f836001600160a01b038416614945565b6138d761462a565b6001600160a01b0382165f90815260db60205260409020600181015415613be7575f8160030154670de0b6b3a764000060cb5484600101546139199190615126565b6139239190615045565b61392d919061501d565b60ca5460408051600481526024810182526020810180516001600160e01b03166339ecce1f60e21b17905290519293505f92839283926001600160a01b03909116916139799190615412565b5f604051808303815f865af19150503d805f81146139b2576040519150601f19603f3d011682016040523d82523d5f602084013e6139b7565b606091505b509150915081156139e8578460060154818060200190518101906139db919061510f565b6139e5919061501d565b92505b8215613ad85760ca546040516001600160a01b0389811660248301529091169060440160408051601f198184030181529181526020820180516001600160e01b03166317b8fb3b60e31b17905251613a409190615412565b5f604051808303815f865af19150503d805f8114613a79576040519150601f19603f3d011682016040523d82523d5f602084013e613a7e565b606091505b5090925090508115613ad8575f81806020019051810190613a9f919061510f565b90505f84876007015483613ab3919061501d565b613abd9088615126565b613ac79190615045565b905085811015613ad5578095505b50505b8360d15f828254613ae9919061501d565b909155505060c95460405163a9059cbb60e01b81526001600160a01b038981166004830152602482018790529091169063a9059cbb906044016020604051808303815f875af1158015613b3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b62919061514a565b613b6a575f80fd5b866001600160a01b03167fe88340f53b0d013ca3a9592feb1a168ed82ebda01019fa89303cb64068251c1285604051613ba591815260200190565b60405180910390a2846003015460d55f828254613bc2919061501d565b9091555050600185015460d680545f90613bdd90849061501d565b9091555050505050505b6001810182905560cf548210613c3057600881015460ff1615155f03613c1c5760d78054905f613c168361537f565b91905055505b60088101805460ff19166001179055613c71565b600881015460ff1615156001148015613c4a57505f60d754115b15613c645760d78054905f613c5e83615030565b91905055505b60088101805460ff191690555b670de0b6b3a764000060cb548260010154613c8c9190615126565b613c969190615045565b6003820181905560d580545f90613cae908490615064565b9091555050600181015460d680545f90613cc9908490615064565b909155505060ce545f0361375e5762278d0060d554670de0b6b3a764000060d65460cb54613cf79190615126565b613d019190615045565b613d0b919061501d565b60d154613d18919061501d565b613d229190615045565b60ce55505050565b60408051610ca081018252684d4d39a2ed88159ea0815268512aafb7dfcee9390060208201526855399ee777cc71d5009181019190915268597c80730a96ae62c06060820152685df5ed4597eb019dc060808201526862a89f8912b6be7e2060a0820152686797744fed3fe226c060c0820152686cc56d53ec4fde5ec060e0820152687235b2cb51ba4476406101008201526877eb95557c36c857c0610120820152687dea900028d322f9806101408201526884364a669144179e40610160820152688ad29aebb221128b006101808201526891c3891114a2e18b006101a082015268990d4feb88de48e1006101c082015268a0b460b74fb5fbfdc06101e082015268a8bd658d46e5be2aa061020082015268b12d443abda46aa44061022082015268ba09213dad85ede2c061024082015268c35662e72966cb806061026082015268cd1ab4a5eb7875a84061028082015268d75c0a7b040af52e006102a082015268e220a49ac43f2407206102c082015268ed6f133c1adbc25a406102e082015268f94e3a98b5ccfec2a0610300820152690105c55720587d7f2e20610320820152690112dc01e1f683f3d9806103408201526901209a352d42d7337ec061036082015269012f08516f862ee2268061038082015269013e2f224eb34b7106006103a082015269014e17e405d5db5ba0c06103c082015269015ecc4906208d34a4806103e0820152690170567fe008944599c0610400820152690182c139780901c131c061042082015269019617af8ad6428f85c06104408201526901aa65ab84fa930c9d406104608201526901bfb78db20719fb45406104808201526901d61a54c7baa816ec406104a08201526901ed9ba5d1b72fc9a7006104c082015269020649d48299f23fa5406104e082015269022033ebef880c28d00061050082015269023b69b7bb820c8a7840610520820152690257fbcdb81559c633c0610540820152690275fb9801499f0456006105608201526902957b5f9af3b29360806105808201526902b68e5795e6478f36006105a08201526902d948a8c3cb65524ec06105c08201526902fdbf7e00c8c61ccc806105e082015269032409111a6c69750a4061060082015269034c3cb85bbea1e42c8061062082015269037672f4c6bb5c70d9006106408201526903a2c58103de5549bdc06106608201526903d14f6110dca60eb2806106808201526904022cf2b81adf40eac06106a08201526904357bfedae906059f006106c082015269046b5bcb990e456dd2006106e08201526904a3ed2f60b563b149806107008201526904df52a4f2580d8ea70061072082015269051db06064dc7854a14061074082015269055f2c6536b446ce0f006107608201526905a3ee9d79707c2c9c006107808201526905ec20f225e9508dcac06107a0820152690637ef64a7ce974d72006107c08201526906878829b03283e89e006107e08201526906db1bc55f683edc44c0610800820152690732dd28d760aa441e8061082082015269078f01d1488be11907c06108408201526907efc1e88c2c7c96c04061086082015269085558675ffb8350e6406108808201526908c0033957fb4b42fc406108a082015269093003629c6175444c806108c08201526909a59d278a9988daa0006108e0820152690a211836518793144480610900820152690aa2bfd2a267fd6bbd80610920820152690b2ae30390ed33437600610940820152690bb9d4c3be92a0719180610960820152690c4fec33ee805e8e7f80610980820152690ced84d020d3981061806109a0820152690d92fea755aaf979ce406109c0820152690e40be9619f3849f96806109e0820152690ef72e8401a61ae2c280610a00820152690fb6bda434ee6cef2600610a2082015269107fe0b93793efff2780610a40820152691153125c13f4eebfdf00610a60820152691230d34714f45dcf0800610a80820152691319aaa43c66f9b70800610aa082015269140e265fa5d28e8b9d00610ac082015269150edb7e07b6a2199a00610ae082015269161c667788196803bf00610b008201526917376b971bb446a2f500610b20820152691860975ea9e3b2a79000610b408201526919989ef0326240c20400610b60820152691ae0407c34e73d96a580610b80820152691c3843b59df2ccc84d80610ba0820152691da17a4b7f721c75db80610bc0820152691f1cc068df6afccd9280610be08201526920aafd3aea96b77cc400610c0082015269224d237ddcb7db92b280610c208201526924043210f48dd58cb000610c408201526925d13491cd94f42dfa00610c608201526927b543ff7e42cefa0a00610c8082015260d9545f919082906301e187e0906143e0904261501d565b6143ea9190615045565b905060645f8183106143fc57816143fe565b825b905083816065811061441257614412615165565b602002015169ffffffffffffffffffff1694505050505090565b5f8060d554670de0b6b3a764000060d654614445614520565b61444f9190615126565b6144599190615045565b614463919061501d565b90508060d154614473919061501d565b91505090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f610d22825490565b5f61226f8383614991565b5f54610100900460ff166145045760405162461bcd60e51b8152600401610d859061542d565b6122956149a6565b5f61226f836001600160a01b0384166149d5565b5f60d6545f03614531575060cb5490565b5f60d65460ce5460d35442614546919061501d565b6145509190615126565b61456290670de0b6b3a7640000615126565b61456c9190615045565b60cb546145799190615064565b90505f60d554670de0b6b3a764000060d654846145969190615126565b6145a09190615045565b6145aa919061501d565b905060d1548110612b06575f60d554670de0b6b3a764000060d65460cb546145d29190615126565b6145dc9190615045565b6145e6919061501d565b60d1546145f3919061501d565b60d65490915061460b82670de0b6b3a7640000615126565b6146159190615045565b60cb546146229190615064565b949350505050565b4260d3540361463557565b60d6541580614644575060ce54155b1561464f574260d355565b5f60d65460ce5460d35442614664919061501d565b61466e9190615126565b61468090670de0b6b3a7640000615126565b61468a9190615045565b60cb546146979190615064565b90505f60d554670de0b6b3a764000060d654846146b49190615126565b6146be9190615045565b6146c8919061501d565b905060d1548110614752575f60d554670de0b6b3a764000060d65460cb546146f09190615126565b6146fa9190615045565b614704919061501d565b60d154614711919061501d565b60d65490915061472982670de0b6b3a7640000615126565b6147339190615045565b60cb5f8282546147439190615064565b90915550505f60ce5550614758565b60cb8290555b50504260d355565b5f805f836001600160a01b031663fc735e9960e01b60405160240161478f9060208082525f9082015260400190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516147cd9190615412565b5f60405180830381855afa9150503d805f8114614805576040519150601f19603f3d011682016040523d82523d5f602084013e61480a565b606091505b509150915081801561483057506122b78180602001905181019061482e919061510f565b115b61487c5760405162461bcd60e51b815260206004820152601760248201527f4e657720636f6e747261637420697320696e76616c69640000000000000000006044820152606401610d85565b5060019392505050565b6001600160a01b0381163b6148f35760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d85565b5f8051602061548d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61492a83614ab8565b5f825111806149365750805b1561375e5761148d8383614af7565b5f81815260018301602052604081205461498a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610d22565b505f610d22565b5f825f01828154811061330a5761330a615165565b5f54610100900460ff166149cc5760405162461bcd60e51b8152600401610d859061542d565b61229533614479565b5f8181526001830160205260408120548015614aaf575f6149f760018361501d565b85549091505f90614a0a9060019061501d565b9050808214614a69575f865f018281548110614a2857614a28615165565b905f5260205f200154905080875f018481548110614a4857614a48615165565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080614a7a57614a7a615478565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610d22565b5f915050610d22565b614ac181614886565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b606061226f83836040518060600160405280602781526020016154ad6027913960605f80856001600160a01b031685604051614b339190615412565b5f60405180830381855af49150503d805f8114614b6b576040519150601f19603f3d011682016040523d82523d5f602084013e614b70565b606091505b5091509150614b8186838387614b8b565b9695505050505050565b60608315614bf95782515f03614bf2576001600160a01b0385163b614bf25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d85565b5081614622565b6146228383815115614c0e5781518083602001fd5b8060405162461bcd60e51b8152600401610d859190614ff7565b80356001600160a01b0381168114614c3e575f80fd5b919050565b5f8060408385031215614c54575f80fd5b614c5d83614c28565b946020939093013593505050565b5f60208284031215614c7b575f80fd5b61226f82614c28565b5f8060408385031215614c95575f80fd5b50508035926020909101359150565b5f8060408385031215614cb5575f80fd5b82359150614cc560208401614c28565b90509250929050565b5f8060408385031215614cdf575f80fd5b614ce883614c28565b9150614cc560208401614c28565b634e487b7160e01b5f52604160045260245ffd5b5f8060408385031215614d1b575f80fd5b614d2483614c28565b9150602083013567ffffffffffffffff80821115614d40575f80fd5b818501915085601f830112614d53575f80fd5b813581811115614d6557614d65614cf6565b604051601f8201601f19908116603f01168101908382118183101715614d8d57614d8d614cf6565b81604052828152886020848701011115614da5575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f8083601f840112614dd6575f80fd5b50813567ffffffffffffffff811115614ded575f80fd5b60208301915083602082850101111561114d575f80fd5b5f805f805f8060808789031215614e19575f80fd5b86359550602087013567ffffffffffffffff80821115614e37575f80fd5b614e438a838b01614dc6565b9097509550604089013594506060890135915080821115614e62575f80fd5b50614e6f89828a01614dc6565b979a9699509497509295939492505050565b5f60208284031215614e91575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015614ed85783516001600160a01b031683529284019291840191600101614eb3565b50909695505050505050565b5f805f805f8060c08789031215614ef9575f80fd5b614f0287614c28565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b5f805f8060608587031215614f3d575f80fd5b84359350614f4d60208601614c28565b9250604085013567ffffffffffffffff811115614f68575f80fd5b614f7487828801614dc6565b95989497509550505050565b5f5b83811015614f9a578181015183820152602001614f82565b50505f910152565b5f8151808452614fb9816020860160208601614f80565b601f01601f19169290920160200192915050565b8315158152606060208201525f614fe76060830185614fa2565b9050826040830152949350505050565b602081525f61226f6020830184614fa2565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d2257610d22615009565b5f8161503e5761503e615009565b505f190190565b5f8261505f57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d2257610d22615009565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f6020828403121561511f575f80fd5b5051919050565b8082028115828204841417610d2257610d22615009565b801515811461122e575f80fd5b5f6020828403121561515a575f80fd5b815161226f8161513d565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061518d57607f821691505b602082108103612b0657634e487b7160e01b5f52602260045260245ffd5b601f82111561375e575f81815260208120601f850160051c810160208610156151d15750805b601f850160051c820191505b818110156151f0578281556001016151dd565b505050505050565b815167ffffffffffffffff81111561521257615212614cf6565b615226816152208454615179565b846151ab565b602080601f831160018114615259575f84156152425750858301515b5f19600386901b1c1916600185901b1785556151f0565b5f85815260208120601f198616915b8281101561528757888601518255948401946001909101908401615268565b50858210156152a457878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b818382375f9101908152919050565b67ffffffffffffffff8311156152db576152db614cf6565b6152ef836152e98354615179565b836151ab565b5f601f841160018114615320575f85156153095750838201355b5f19600387901b1c1916600186901b178355615378565b5f83815260209020601f19861690835b828110156153505786850135825560209485019460019092019101615330565b508682101561536c575f1960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b5f6001820161539057615390615009565b5060010190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b606081525f6153d2606083018789615397565b85602084015282810360408401526153eb818587615397565b98975050505050505050565b5f60208284031215615407575f80fd5b813561226f8161513d565b5f8251615423818460208701614f80565b9190910192915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b5f52603160045260245ffdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122032447ae98509ab4e45c964753eb29eb87099951f0fccdd08fb100c368c7db06264736f6c63430008140033