文件 1 的 7:Governance.sol
pragma solidity 0.8.3;
import "./interfaces/IOracle.sol";
import "./interfaces/IERC20.sol";
import "usingtellor/contracts/UsingTellor.sol";
contract Governance is UsingTellor {
IOracle public oracle;
IERC20 public token;
address public oracleAddress;
address public teamMultisig;
uint256 public voteCount;
bytes32 public autopayAddrsQueryId =
keccak256(abi.encode("AutopayAddresses", abi.encode(bytes(""))));
mapping(uint256 => Dispute) private disputeInfo;
mapping(bytes32 => uint256) private openDisputesOnId;
mapping(uint256 => Vote) private voteInfo;
mapping(bytes32 => uint256[]) private voteRounds;
mapping(address => uint256) private voteTallyByAddress;
mapping(address => uint256[]) private disputeIdsByReporter;
enum VoteResult {
FAILED,
PASSED,
INVALID
}
struct Dispute {
bytes32 queryId;
uint256 timestamp;
bytes value;
address disputedReporter;
uint256 slashedAmount;
}
struct Tally {
uint256 doesSupport;
uint256 against;
uint256 invalidQuery;
}
struct Vote {
bytes32 identifierHash;
uint256 voteRound;
uint256 startDate;
uint256 blockNumber;
uint256 fee;
uint256 tallyDate;
Tally tokenholders;
Tally users;
Tally reporters;
Tally teamMultisig;
bool executed;
VoteResult result;
address initiator;
mapping(address => bool) voted;
}
event NewDispute(
uint256 _disputeId,
bytes32 _queryId,
uint256 _timestamp,
address _reporter
);
event Voted(
uint256 _disputeId,
bool _supports,
address _voter,
bool _invalidQuery
);
event VoteExecuted(uint256 _disputeId, VoteResult _result);
event VoteTallied(
uint256 _disputeId,
VoteResult _result,
address _initiator,
address _reporter
);
constructor(
address payable _tellor,
address _teamMultisig
) UsingTellor(_tellor) {
oracle = IOracle(_tellor);
token = IERC20(oracle.getTokenAddress());
oracleAddress = _tellor;
teamMultisig = _teamMultisig;
}
function beginDispute(bytes32 _queryId, uint256 _timestamp) external {
address _reporter = oracle.getReporterByTimestamp(_queryId, _timestamp);
require(_reporter != address(0), "no value exists at given timestamp");
bytes32 _hash = keccak256(abi.encodePacked(_queryId, _timestamp));
uint256 _disputeId = voteCount + 1;
uint256[] storage _voteRounds = voteRounds[_hash];
_voteRounds.push(_disputeId);
Vote storage _thisVote = voteInfo[_disputeId];
Dispute storage _thisDispute = disputeInfo[_disputeId];
_thisDispute.queryId = _queryId;
_thisDispute.timestamp = _timestamp;
_thisDispute.disputedReporter = _reporter;
_thisVote.identifierHash = _hash;
_thisVote.initiator = msg.sender;
_thisVote.blockNumber = block.number;
_thisVote.startDate = block.timestamp;
_thisVote.voteRound = _voteRounds.length;
disputeIdsByReporter[_reporter].push(_disputeId);
uint256 _disputeFee = getDisputeFee();
if (_voteRounds.length == 1) {
require(
block.timestamp - _timestamp < 12 hours,
"Dispute must be started within reporting lock time"
);
openDisputesOnId[_queryId]++;
if (openDisputesOnId[_queryId] > 4) {
_disputeFee = oracle.getStakeAmount();
} else {
_disputeFee =
_disputeFee *
2 ** (openDisputesOnId[_queryId] - 1);
}
_thisDispute.slashedAmount = oracle.slashReporter(
_reporter,
address(this)
);
_thisDispute.value = oracle.retrieveData(_queryId, _timestamp);
oracle.removeValue(_queryId, _timestamp);
} else {
uint256 _prevId = _voteRounds[_voteRounds.length - 2];
require(
block.timestamp - voteInfo[_prevId].tallyDate < 1 days,
"New dispute round must be started within a day"
);
if (_voteRounds.length > 4) {
_disputeFee = oracle.getStakeAmount();
} else {
_disputeFee = _disputeFee * 2 ** (_voteRounds.length - 1);
}
_thisDispute.slashedAmount = disputeInfo[_voteRounds[0]]
.slashedAmount;
_thisDispute.value = disputeInfo[_voteRounds[0]].value;
}
_thisVote.fee = _disputeFee;
voteCount++;
require(
token.transferFrom(msg.sender, address(this), _disputeFee),
"Fee must be paid"
);
emit NewDispute(_disputeId, _queryId, _timestamp, _reporter);
}
function executeVote(uint256 _disputeId) external {
Vote storage _thisVote = voteInfo[_disputeId];
require(
_disputeId <= voteCount && _disputeId > 0,
"Dispute ID must be valid"
);
require(!_thisVote.executed, "Vote has already been executed");
require(_thisVote.tallyDate > 0, "Vote must be tallied");
require(
voteRounds[_thisVote.identifierHash].length == _thisVote.voteRound,
"Must be the final vote"
);
require(
block.timestamp - _thisVote.tallyDate >= 1 days,
"1 day has to pass after tally to allow for disputes"
);
_thisVote.executed = true;
Dispute storage _thisDispute = disputeInfo[_disputeId];
openDisputesOnId[_thisDispute.queryId]--;
uint256 _i;
uint256 _voteID;
if (_thisVote.result == VoteResult.PASSED) {
for (
_i = voteRounds[_thisVote.identifierHash].length;
_i > 0;
_i--
) {
_voteID = voteRounds[_thisVote.identifierHash][_i - 1];
_thisVote = voteInfo[_voteID];
if (_i == 1) {
token.transfer(
_thisVote.initiator,
_thisDispute.slashedAmount
);
}
token.transfer(_thisVote.initiator, _thisVote.fee);
}
} else if (_thisVote.result == VoteResult.INVALID) {
for (
_i = voteRounds[_thisVote.identifierHash].length;
_i > 0;
_i--
) {
_voteID = voteRounds[_thisVote.identifierHash][_i - 1];
_thisVote = voteInfo[_voteID];
token.transfer(_thisVote.initiator, _thisVote.fee);
}
token.transfer(
_thisDispute.disputedReporter,
_thisDispute.slashedAmount
);
} else if (_thisVote.result == VoteResult.FAILED) {
uint256 _reporterReward = 0;
for (
_i = voteRounds[_thisVote.identifierHash].length;
_i > 0;
_i--
) {
_voteID = voteRounds[_thisVote.identifierHash][_i - 1];
_thisVote = voteInfo[_voteID];
_reporterReward += _thisVote.fee;
}
_reporterReward += _thisDispute.slashedAmount;
token.transfer(_thisDispute.disputedReporter, _reporterReward);
}
emit VoteExecuted(_disputeId, voteInfo[_disputeId].result);
}
function tallyVotes(uint256 _disputeId) external {
Vote storage _thisVote = voteInfo[_disputeId];
require(_thisVote.tallyDate == 0, "Vote has already been tallied");
require(
_disputeId <= voteCount && _disputeId > 0,
"Vote does not exist"
);
require(
block.timestamp - _thisVote.startDate >=
86400 * _thisVote.voteRound ||
block.timestamp - _thisVote.startDate >= 86400 * 6,
"Time for voting has not elapsed"
);
uint256 _tokenVoteSum = _thisVote.tokenholders.doesSupport +
_thisVote.tokenholders.against +
_thisVote.tokenholders.invalidQuery;
uint256 _reportersVoteSum = _thisVote.reporters.doesSupport +
_thisVote.reporters.against +
_thisVote.reporters.invalidQuery;
uint256 _multisigVoteSum = _thisVote.teamMultisig.doesSupport +
_thisVote.teamMultisig.against +
_thisVote.teamMultisig.invalidQuery;
uint256 _usersVoteSum = _thisVote.users.doesSupport +
_thisVote.users.against +
_thisVote.users.invalidQuery;
if (_tokenVoteSum == 0) {
_tokenVoteSum++;
}
if (_reportersVoteSum == 0) {
_reportersVoteSum++;
}
if (_multisigVoteSum == 0) {
_multisigVoteSum++;
}
if (_usersVoteSum == 0) {
_usersVoteSum++;
}
uint256 _scaledDoesSupport = ((_thisVote.tokenholders.doesSupport *
1e18) / _tokenVoteSum) +
((_thisVote.reporters.doesSupport * 1e18) / _reportersVoteSum) +
((_thisVote.teamMultisig.doesSupport * 1e18) / _multisigVoteSum) +
((_thisVote.users.doesSupport * 1e18) / _usersVoteSum);
uint256 _scaledAgainst = ((_thisVote.tokenholders.against * 1e18) /
_tokenVoteSum) +
((_thisVote.reporters.against * 1e18) / _reportersVoteSum) +
((_thisVote.teamMultisig.against * 1e18) / _multisigVoteSum) +
((_thisVote.users.against * 1e18) / _usersVoteSum);
uint256 _scaledInvalid = ((_thisVote.tokenholders.invalidQuery * 1e18) /
_tokenVoteSum) +
((_thisVote.reporters.invalidQuery * 1e18) / _reportersVoteSum) +
((_thisVote.teamMultisig.invalidQuery * 1e18) / _multisigVoteSum) +
((_thisVote.users.invalidQuery * 1e18) / _usersVoteSum);
if (_scaledDoesSupport > _scaledAgainst + _scaledInvalid) {
_thisVote.result = VoteResult.PASSED;
} else if (_scaledAgainst > _scaledDoesSupport + _scaledInvalid) {
_thisVote.result = VoteResult.FAILED;
} else {
_thisVote.result = VoteResult.INVALID;
}
_thisVote.tallyDate = block.timestamp;
emit VoteTallied(
_disputeId,
_thisVote.result,
_thisVote.initiator,
disputeInfo[_disputeId].disputedReporter
);
}
function vote(
uint256 _disputeId,
bool _supports,
bool _invalidQuery
) public {
require(
_disputeId <= voteCount && _disputeId > 0,
"Vote does not exist"
);
Vote storage _thisVote = voteInfo[_disputeId];
require(_thisVote.tallyDate == 0, "Vote has already been tallied");
require(!_thisVote.voted[msg.sender], "Sender has already voted");
_thisVote.voted[msg.sender] = true;
uint256 _tokenBalance = token.balanceOf(msg.sender);
(, uint256 _stakedBalance, uint256 _lockedBalance, , , , , ) = oracle
.getStakerInfo(msg.sender);
_tokenBalance += _stakedBalance + _lockedBalance;
if (_invalidQuery) {
_thisVote.tokenholders.invalidQuery += _tokenBalance;
_thisVote.reporters.invalidQuery += oracle
.getReportsSubmittedByAddress(msg.sender);
_thisVote.users.invalidQuery += _getUserTips(msg.sender);
if (msg.sender == teamMultisig) {
_thisVote.teamMultisig.invalidQuery += 1;
}
} else if (_supports) {
_thisVote.tokenholders.doesSupport += _tokenBalance;
_thisVote.reporters.doesSupport += oracle
.getReportsSubmittedByAddress(msg.sender);
_thisVote.users.doesSupport += _getUserTips(msg.sender);
if (msg.sender == teamMultisig) {
_thisVote.teamMultisig.doesSupport += 1;
}
} else {
_thisVote.tokenholders.against += _tokenBalance;
_thisVote.reporters.against += oracle.getReportsSubmittedByAddress(
msg.sender
);
_thisVote.users.against += _getUserTips(msg.sender);
if (msg.sender == teamMultisig) {
_thisVote.teamMultisig.against += 1;
}
}
voteTallyByAddress[msg.sender]++;
emit Voted(_disputeId, _supports, msg.sender, _invalidQuery);
}
function voteOnMultipleDisputes(
uint256[] memory _disputeIds,
bool[] memory _supports,
bool[] memory _invalidQuery
) external {
for (uint256 _i = 0; _i < _disputeIds.length; _i++) {
vote(_disputeIds[_i], _supports[_i], _invalidQuery[_i]);
}
}
function didVote(
uint256 _disputeId,
address _voter
) external view returns (bool) {
return voteInfo[_disputeId].voted[_voter];
}
function getDisputeFee() public view returns (uint256) {
return (oracle.getStakeAmount() / 10);
}
function getDisputesByReporter(
address _reporter
) external view returns (uint256[] memory) {
return disputeIdsByReporter[_reporter];
}
function getDisputeInfo(
uint256 _disputeId
) external view returns (bytes32, uint256, bytes memory, address) {
Dispute storage _d = disputeInfo[_disputeId];
return (_d.queryId, _d.timestamp, _d.value, _d.disputedReporter);
}
function getOpenDisputesOnId(
bytes32 _queryId
) external view returns (uint256) {
return openDisputesOnId[_queryId];
}
function getVoteCount() external view returns (uint256) {
return voteCount;
}
function getVoteInfo(
uint256 _disputeId
)
external
view
returns (bytes32, uint256[17] memory, bool, VoteResult, address)
{
Vote storage _v = voteInfo[_disputeId];
return (
_v.identifierHash,
[
_v.voteRound,
_v.startDate,
_v.blockNumber,
_v.fee,
_v.tallyDate,
_v.tokenholders.doesSupport,
_v.tokenholders.against,
_v.tokenholders.invalidQuery,
_v.users.doesSupport,
_v.users.against,
_v.users.invalidQuery,
_v.reporters.doesSupport,
_v.reporters.against,
_v.reporters.invalidQuery,
_v.teamMultisig.doesSupport,
_v.teamMultisig.against,
_v.teamMultisig.invalidQuery
],
_v.executed,
_v.result,
_v.initiator
);
}
function getVoteRounds(
bytes32 _hash
) external view returns (uint256[] memory) {
return voteRounds[_hash];
}
function getVoteTallyByAddress(
address _voter
) external view returns (uint256) {
return voteTallyByAddress[_voter];
}
function _getUserTips(
address _user
) internal returns (uint256 _userTipTally) {
(bytes memory _autopayAddrsBytes, uint256 _timestamp) = getDataBefore(
autopayAddrsQueryId,
block.timestamp - 12 hours
);
if (_timestamp > 0) {
address[] memory _autopayAddrs = abi.decode(
_autopayAddrsBytes,
(address[])
);
for (uint256 _i = 0; _i < _autopayAddrs.length; _i++) {
(bool _success, bytes memory _returnData) = _autopayAddrs[_i]
.call(
abi.encodeWithSignature(
"getTipsByAddress(address)",
_user
)
);
if (_success) {
_userTipTally += abi.decode(_returnData, (uint256));
}
}
}
}
}
文件 2 的 7:IERC20.sol
pragma solidity 0.8.3;
interface IERC20 {
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);
}
文件 3 的 7:IERC2362.sol
pragma solidity >=0.8.0;
interface IERC2362
{
function valueFor(bytes32 _id) external view returns(int256,uint256,uint256);
}
文件 4 的 7:IMappingContract.sol
pragma solidity ^0.8.0;
interface IMappingContract{
function getTellorID(bytes32 _id) external view returns(bytes32);
}
文件 5 的 7:IOracle.sol
pragma solidity 0.8.3;
interface IOracle {
function removeValue(bytes32 _queryId, uint256 _timestamp) external;
function slashReporter(address _reporter, address _recipient)
external
returns (uint256);
function getBlockNumberByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (uint256);
function getReporterByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (address);
function getReportsSubmittedByAddress(address _reporter)
external
view
returns (uint256);
function getStakeAmount() external view returns (uint256);
function getStakerInfo(address _stakerAddress)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256
);
function getDataBefore(bytes32 _queryId, uint256 _timestamp)
external
view
returns (
bool _ifRetrieve,
bytes memory _value,
uint256 _timestampRetrieved
);
function getTokenAddress() external view returns (address);
function retrieveData(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bytes memory);
}
文件 6 的 7:ITellor.sol
pragma solidity >=0.8.0;
interface ITellor {
function addresses(bytes32) external view returns (address);
function uints(bytes32) external view returns (uint256);
function burn(uint256 _amount) external;
function changeDeity(address _newDeity) external;
function changeOwner(address _newOwner) external;
function changeUint(bytes32 _target, uint256 _amount) external;
function migrate() external;
function mint(address _reciever, uint256 _amount) external;
function init() external;
function getAllDisputeVars(uint256 _disputeId)
external
view
returns (
bytes32,
bool,
bool,
bool,
address,
address,
address,
uint256[9] memory,
int256
);
function getDisputeIdByDisputeHash(bytes32 _hash)
external
view
returns (uint256);
function getDisputeUintVars(uint256 _disputeId, bytes32 _data)
external
view
returns (uint256);
function getLastNewValueById(uint256 _requestId)
external
view
returns (uint256, bool);
function retrieveData(uint256 _requestId, uint256 _timestamp)
external
view
returns (uint256);
function getNewValueCountbyRequestId(uint256 _requestId)
external
view
returns (uint256);
function getAddressVars(bytes32 _data) external view returns (address);
function getUintVar(bytes32 _data) external view returns (uint256);
function totalSupply() external view returns (uint256);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function isMigrated(address _addy) external view returns (bool);
function allowance(address _user, address _spender)
external
view
returns (uint256);
function allowedToTrade(address _user, uint256 _amount)
external
view
returns (bool);
function approve(address _spender, uint256 _amount) external returns (bool);
function approveAndTransferFrom(
address _from,
address _to,
uint256 _amount
) external returns (bool);
function balanceOf(address _user) external view returns (uint256);
function balanceOfAt(address _user, uint256 _blockNumber)
external
view
returns (uint256);
function transfer(address _to, uint256 _amount)
external
returns (bool success);
function transferFrom(
address _from,
address _to,
uint256 _amount
) external returns (bool success);
function depositStake() external;
function requestStakingWithdraw() external;
function withdrawStake() external;
function changeStakingStatus(address _reporter, uint256 _status) external;
function slashReporter(address _reporter, address _disputer) external;
function getStakerInfo(address _staker)
external
view
returns (uint256, uint256);
function getTimestampbyRequestIDandIndex(uint256 _requestId, uint256 _index)
external
view
returns (uint256);
function getNewCurrentVariables()
external
view
returns (
bytes32 _c,
uint256[5] memory _r,
uint256 _d,
uint256 _t
);
function getNewValueCountbyQueryId(bytes32 _queryId)
external
view
returns (uint256);
function getTimestampbyQueryIdandIndex(bytes32 _queryId, uint256 _index)
external
view
returns (uint256);
function retrieveData(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bytes memory);
enum VoteResult {
FAILED,
PASSED,
INVALID
}
function setApprovedFunction(bytes4 _func, bool _val) external;
function beginDispute(bytes32 _queryId, uint256 _timestamp) external;
function delegate(address _delegate) external;
function delegateOfAt(address _user, uint256 _blockNumber)
external
view
returns (address);
function executeVote(uint256 _disputeId) external;
function proposeVote(
address _contract,
bytes4 _function,
bytes calldata _data,
uint256 _timestamp
) external;
function tallyVotes(uint256 _disputeId) external;
function governance() external view returns (address);
function updateMinDisputeFee() external;
function verify() external pure returns (uint256);
function vote(
uint256 _disputeId,
bool _supports,
bool _invalidQuery
) external;
function voteFor(
address[] calldata _addys,
uint256 _disputeId,
bool _supports,
bool _invalidQuery
) external;
function getDelegateInfo(address _holder)
external
view
returns (address, uint256);
function isFunctionApproved(bytes4 _func) external view returns (bool);
function isApprovedGovernanceContract(address _contract)
external
returns (bool);
function getVoteRounds(bytes32 _hash)
external
view
returns (uint256[] memory);
function getVoteCount() external view returns (uint256);
function getVoteInfo(uint256 _disputeId)
external
view
returns (
bytes32,
uint256[9] memory,
bool[2] memory,
VoteResult,
bytes memory,
bytes4,
address[2] memory
);
function getDisputeInfo(uint256 _disputeId)
external
view
returns (
uint256,
uint256,
bytes memory,
address
);
function getOpenDisputesOnId(bytes32 _queryId)
external
view
returns (uint256);
function didVote(uint256 _disputeId, address _voter)
external
view
returns (bool);
function getReportTimestampByIndex(bytes32 _queryId, uint256 _index)
external
view
returns (uint256);
function getValueByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bytes memory);
function getBlockNumberByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (uint256);
function getReportingLock() external view returns (uint256);
function getReporterByTimestamp(bytes32 _queryId, uint256 _timestamp)
external
view
returns (address);
function reportingLock() external view returns (uint256);
function removeValue(bytes32 _queryId, uint256 _timestamp) external;
function getTipsByUser(address _user) external view returns(uint256);
function tipQuery(bytes32 _queryId, uint256 _tip, bytes memory _queryData) external;
function submitValue(bytes32 _queryId, bytes calldata _value, uint256 _nonce, bytes memory _queryData) external;
function burnTips() external;
function changeReportingLock(uint256 _newReportingLock) external;
function getReportsSubmittedByAddress(address _reporter) external view returns(uint256);
function changeTimeBasedReward(uint256 _newTimeBasedReward) external;
function getReporterLastTimestamp(address _reporter) external view returns(uint256);
function getTipsById(bytes32 _queryId) external view returns(uint256);
function getTimeBasedReward() external view returns(uint256);
function getTimestampCountById(bytes32 _queryId) external view returns(uint256);
function getTimestampIndexByTimestamp(bytes32 _queryId, uint256 _timestamp) external view returns(uint256);
function getCurrentReward(bytes32 _queryId) external view returns(uint256, uint256);
function getCurrentValue(bytes32 _queryId) external view returns(bytes memory);
function getDataBefore(bytes32 _queryId, uint256 _timestamp) external view returns(bool _ifRetrieve, bytes memory _value, uint256 _timestampRetrieved);
function getTimeOfLastNewValue() external view returns(uint256);
function depositStake(uint256 _amount) external;
function requestStakingWithdraw(uint256 _amount) external;
function changeAddressVar(bytes32 _id, address _addy) external;
function killContract() external;
function migrateFor(address _destination, uint256 _amount) external;
function rescue51PercentAttack(address _tokenHolder) external;
function rescueBrokenDataReporting() external;
function rescueFailedUpdate() external;
function addStakingRewards(uint256 _amount) external;
function _sliceUint(bytes memory _b)
external
pure
returns (uint256 _number);
function claimOneTimeTip(bytes32 _queryId, uint256[] memory _timestamps)
external;
function claimTip(
bytes32 _feedId,
bytes32 _queryId,
uint256[] memory _timestamps
) external;
function fee() external view returns (uint256);
function feedsWithFunding(uint256) external view returns (bytes32);
function fundFeed(
bytes32 _feedId,
bytes32 _queryId,
uint256 _amount
) external;
function getCurrentFeeds(bytes32 _queryId)
external
view
returns (bytes32[] memory);
function getCurrentTip(bytes32 _queryId) external view returns (uint256);
function getDataAfter(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bytes memory _value, uint256 _timestampRetrieved);
function getDataFeed(bytes32 _feedId)
external
view
returns (Autopay.FeedDetails memory);
function getFundedFeeds() external view returns (bytes32[] memory);
function getFundedQueryIds() external view returns (bytes32[] memory);
function getIndexForDataAfter(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bool _found, uint256 _index);
function getIndexForDataBefore(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bool _found, uint256 _index);
function getMultipleValuesBefore(
bytes32 _queryId,
uint256 _timestamp,
uint256 _maxAge,
uint256 _maxCount
)
external
view
returns (uint256[] memory _values, uint256[] memory _timestamps);
function getPastTipByIndex(bytes32 _queryId, uint256 _index)
external
view
returns (Autopay.Tip memory);
function getPastTipCount(bytes32 _queryId) external view returns (uint256);
function getPastTips(bytes32 _queryId)
external
view
returns (Autopay.Tip[] memory);
function getQueryIdFromFeedId(bytes32 _feedId)
external
view
returns (bytes32);
function getRewardAmount(
bytes32 _feedId,
bytes32 _queryId,
uint256[] memory _timestamps
) external view returns (uint256 _cumulativeReward);
function getRewardClaimedStatus(
bytes32 _feedId,
bytes32 _queryId,
uint256 _timestamp
) external view returns (bool);
function getTipsByAddress(address _user) external view returns (uint256);
function isInDispute(bytes32 _queryId, uint256 _timestamp)
external
view
returns (bool);
function queryIdFromDataFeedId(bytes32) external view returns (bytes32);
function queryIdsWithFunding(uint256) external view returns (bytes32);
function queryIdsWithFundingIndex(bytes32) external view returns (uint256);
function setupDataFeed(
bytes32 _queryId,
uint256 _reward,
uint256 _startTime,
uint256 _interval,
uint256 _window,
uint256 _priceThreshold,
uint256 _rewardIncreasePerSecond,
bytes memory _queryData,
uint256 _amount
) external;
function tellor() external view returns (address);
function tip(
bytes32 _queryId,
uint256 _amount,
bytes memory _queryData
) external;
function tips(bytes32, uint256)
external
view
returns (uint256 amount, uint256 timestamp);
function token() external view returns (address);
function userTipsTotal(address) external view returns (uint256);
function valueFor(bytes32 _id)
external
view
returns (
int256 _value,
uint256 _timestamp,
uint256 _statusCode
);
}
interface Autopay {
struct FeedDetails {
uint256 reward;
uint256 balance;
uint256 startTime;
uint256 interval;
uint256 window;
uint256 priceThreshold;
uint256 rewardIncreasePerSecond;
uint256 feedsWithFundingIndex;
}
struct Tip {
uint256 amount;
uint256 timestamp;
}
function getStakeAmount() external view returns(uint256);
function stakeAmount() external view returns(uint256);
function token() external view returns(address);
}
文件 7 的 7:UsingTellor.sol
pragma solidity >=0.8.0;
import "./interface/ITellor.sol";
import "./interface/IERC2362.sol";
import "./interface/IMappingContract.sol";
contract UsingTellor is IERC2362 {
ITellor public tellor;
IMappingContract public idMappingContract;
constructor(address payable _tellor) {
tellor = ITellor(_tellor);
}
function getDataAfter(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bytes memory _value, uint256 _timestampRetrieved)
{
(bool _found, uint256 _index) = getIndexForDataAfter(
_queryId,
_timestamp
);
if (!_found) {
return ("", 0);
}
_timestampRetrieved = getTimestampbyQueryIdandIndex(_queryId, _index);
_value = retrieveData(_queryId, _timestampRetrieved);
return (_value, _timestampRetrieved);
}
function getDataBefore(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bytes memory _value, uint256 _timestampRetrieved)
{
(, _value, _timestampRetrieved) = tellor.getDataBefore(
_queryId,
_timestamp
);
}
function getIndexForDataAfter(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bool _found, uint256 _index)
{
uint256 _count = getNewValueCountbyQueryId(_queryId);
if (_count == 0) return (false, 0);
_count--;
bool _search = true;
uint256 _middle = 0;
uint256 _start = 0;
uint256 _end = _count;
uint256 _timestampRetrieved;
_timestampRetrieved = getTimestampbyQueryIdandIndex(_queryId, _end);
if (_timestampRetrieved <= _timestamp) return (false, 0);
_timestampRetrieved = getTimestampbyQueryIdandIndex(_queryId, _start);
if (_timestampRetrieved > _timestamp) {
_search = false;
}
while (_search) {
_middle = (_end + _start) / 2;
_timestampRetrieved = getTimestampbyQueryIdandIndex(
_queryId,
_middle
);
if (_timestampRetrieved > _timestamp) {
uint256 _prevTime = getTimestampbyQueryIdandIndex(
_queryId,
_middle - 1
);
if (_prevTime <= _timestamp) {
_search = false;
} else {
_end = _middle - 1;
}
} else {
uint256 _nextTime = getTimestampbyQueryIdandIndex(
_queryId,
_middle + 1
);
if (_nextTime > _timestamp) {
_search = false;
_middle++;
_timestampRetrieved = _nextTime;
} else {
_start = _middle + 1;
}
}
}
if (!isInDispute(_queryId, _timestampRetrieved)) {
return (true, _middle);
} else {
while (
isInDispute(_queryId, _timestampRetrieved) && _middle < _count
) {
_middle++;
_timestampRetrieved = getTimestampbyQueryIdandIndex(
_queryId,
_middle
);
}
if (
_middle == _count && isInDispute(_queryId, _timestampRetrieved)
) {
return (false, 0);
}
return (true, _middle);
}
}
function getIndexForDataBefore(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bool _found, uint256 _index)
{
return tellor.getIndexForDataBefore(_queryId, _timestamp);
}
function getMultipleValuesBefore(
bytes32 _queryId,
uint256 _timestamp,
uint256 _maxAge,
uint256 _maxCount
)
public
view
returns (bytes[] memory _values, uint256[] memory _timestamps)
{
(bool _ifRetrieve, uint256 _startIndex) = getIndexForDataAfter(
_queryId,
_timestamp - _maxAge
);
if (!_ifRetrieve) {
return (new bytes[](0), new uint256[](0));
}
uint256 _endIndex;
(_ifRetrieve, _endIndex) = getIndexForDataBefore(_queryId, _timestamp);
if (!_ifRetrieve) {
return (new bytes[](0), new uint256[](0));
}
uint256 _valCount = 0;
uint256 _index = 0;
uint256[] memory _timestampsArrayTemp = new uint256[](_maxCount);
while (_valCount < _maxCount && _endIndex + 1 - _index > _startIndex) {
uint256 _timestampRetrieved = getTimestampbyQueryIdandIndex(
_queryId,
_endIndex - _index
);
if (!isInDispute(_queryId, _timestampRetrieved)) {
_timestampsArrayTemp[_valCount] = _timestampRetrieved;
_valCount++;
}
_index++;
}
bytes[] memory _valuesArray = new bytes[](_valCount);
uint256[] memory _timestampsArray = new uint256[](_valCount);
for (uint256 _i = 0; _i < _valCount; _i++) {
_timestampsArray[_i] = _timestampsArrayTemp[_valCount - 1 - _i];
_valuesArray[_i] = retrieveData(_queryId, _timestampsArray[_i]);
}
return (_valuesArray, _timestampsArray);
}
function getNewValueCountbyQueryId(bytes32 _queryId)
public
view
returns (uint256)
{
return tellor.getNewValueCountbyQueryId(_queryId);
}
function getReporterByTimestamp(bytes32 _queryId, uint256 _timestamp)
public
view
returns (address)
{
return tellor.getReporterByTimestamp(_queryId, _timestamp);
}
function getTimestampbyQueryIdandIndex(bytes32 _queryId, uint256 _index)
public
view
returns (uint256)
{
return tellor.getTimestampbyQueryIdandIndex(_queryId, _index);
}
function isInDispute(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bool)
{
return tellor.isInDispute(_queryId, _timestamp);
}
function retrieveData(bytes32 _queryId, uint256 _timestamp)
public
view
returns (bytes memory)
{
return tellor.retrieveData(_queryId, _timestamp);
}
function setIdMappingContract(address _addy) external {
require(address(idMappingContract) == address(0));
idMappingContract = IMappingContract(_addy);
}
function valueFor(bytes32 _id)
external
view
override
returns (
int256 _value,
uint256 _timestamp,
uint256 _statusCode
)
{
bytes32 _queryId = idMappingContract.getTellorID(_id);
bytes memory _valueBytes;
(_valueBytes, _timestamp) = getDataBefore(
_queryId,
block.timestamp + 1
);
if (_timestamp == 0) {
return (0, 0, 404);
}
uint256 _valueUint = _sliceUint(_valueBytes);
_value = int256(_valueUint);
return (_value, _timestamp, 200);
}
function _sliceUint(bytes memory _b)
internal
pure
returns (uint256 _number)
{
for (uint256 _i = 0; _i < _b.length; _i++) {
_number = _number * 256 + uint8(_b[_i]);
}
}
}
{
"compilationTarget": {
"polygongovernance/contracts/Governance.sol": "Governance"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 300
},
"remappings": []
}
[{"inputs":[{"internalType":"address payable","name":"_tellor","type":"address"},{"internalType":"address","name":"_teamMultisig","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_disputeId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"_reporter","type":"address"}],"name":"NewDispute","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_disputeId","type":"uint256"},{"indexed":false,"internalType":"enum Governance.VoteResult","name":"_result","type":"uint8"}],"name":"VoteExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_disputeId","type":"uint256"},{"indexed":false,"internalType":"enum Governance.VoteResult","name":"_result","type":"uint8"},{"indexed":false,"internalType":"address","name":"_initiator","type":"address"},{"indexed":false,"internalType":"address","name":"_reporter","type":"address"}],"name":"VoteTallied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_disputeId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_supports","type":"bool"},{"indexed":false,"internalType":"address","name":"_voter","type":"address"},{"indexed":false,"internalType":"bool","name":"_invalidQuery","type":"bool"}],"name":"Voted","type":"event"},{"inputs":[],"name":"autopayAddrsQueryId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"beginDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"},{"internalType":"address","name":"_voter","type":"address"}],"name":"didVote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"executeVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getDataAfter","outputs":[{"internalType":"bytes","name":"_value","type":"bytes"},{"internalType":"uint256","name":"_timestampRetrieved","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getDataBefore","outputs":[{"internalType":"bytes","name":"_value","type":"bytes"},{"internalType":"uint256","name":"_timestampRetrieved","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDisputeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"getDisputeInfo","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reporter","type":"address"}],"name":"getDisputesByReporter","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getIndexForDataAfter","outputs":[{"internalType":"bool","name":"_found","type":"bool"},{"internalType":"uint256","name":"_index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getIndexForDataBefore","outputs":[{"internalType":"bool","name":"_found","type":"bool"},{"internalType":"uint256","name":"_index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_maxAge","type":"uint256"},{"internalType":"uint256","name":"_maxCount","type":"uint256"}],"name":"getMultipleValuesBefore","outputs":[{"internalType":"bytes[]","name":"_values","type":"bytes[]"},{"internalType":"uint256[]","name":"_timestamps","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"}],"name":"getNewValueCountbyQueryId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"}],"name":"getOpenDisputesOnId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getReporterByTimestamp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTimestampbyQueryIdandIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVoteCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"getVoteInfo","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256[17]","name":"","type":"uint256[17]"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"enum Governance.VoteResult","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"getVoteRounds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_voter","type":"address"}],"name":"getVoteTallyByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"idMappingContract","outputs":[{"internalType":"contract IMappingContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"isInDispute","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_queryId","type":"bytes32"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"retrieveData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addy","type":"address"}],"name":"setIdMappingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"tallyVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"teamMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tellor","outputs":[{"internalType":"contract ITellor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"valueFor","outputs":[{"internalType":"int256","name":"_value","type":"int256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_statusCode","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"},{"internalType":"bool","name":"_supports","type":"bool"},{"internalType":"bool","name":"_invalidQuery","type":"bool"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voteCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_disputeIds","type":"uint256[]"},{"internalType":"bool[]","name":"_supports","type":"bool[]"},{"internalType":"bool[]","name":"_invalidQuery","type":"bool[]"}],"name":"voteOnMultipleDisputes","outputs":[],"stateMutability":"nonpayable","type":"function"}]