Contract 0x3eb81A11DD28Fe8ED9f53D1456248aC86d5893C6 4

Contract Overview

Balance:
0 Ether
Txn Hash
Method
Block
From
To
Value
0x0cb4d2b161acfcce66440c96b565f15789197c661a8babd6d97943273a3b57400x60806040321051032022-06-10 14:37:2862 days 3 hrs ago0x79ef1fba1480b2d06cbd8fa67260a906909246f9 IN  Create: Governance0 Ether0.‍00448496 1.‍5
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0x0cb4d2b161acfcce66440c96b565f15789197c661a8babd6d97943273a3b5740321051032022-06-10 14:37:2862 days 3 hrs ago 0x3eb81a11dd28fe8ed9f53d1456248ac86d5893c6 0xbb97c038c338c3dcaf06d5be3b4a3e0b24835f9c0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Governance

Compiler Version
v0.8.3+commit.8d00100c

Optimization Enabled:
Yes with 300 runs

Other Settings:
default evmVersion
File 1 of 3 : Governance.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

import "./TellorFlex.sol";

/**
 @author Tellor Inc.
 @title Governance
 @dev This is a governance contract to be used with TellorFlex. It handles disputing
 * Tellor oracle data, proposing system parameter changes, and voting on those
 * disputes and proposals.
*/
contract Governance {
    // Storage
    TellorFlex public tellor; // Tellor oracle contract
    IERC20 public token; // token used for dispute fees, same as reporter staking token
    address public teamMultisig; // address of team multisig wallet, one of four stakeholder groups
    uint256 public voteCount; // total number of votes initiated
    uint256 public disputeFee; // dispute fee for a vote
    mapping(uint256 => Dispute) private disputeInfo; // mapping of dispute IDs to the details of the dispute
    mapping(bytes32 => uint256) private openDisputesOnId; // mapping of a query ID to the number of disputes on that query ID
    mapping(address => bool) private users; // mapping of users with voting power, determined by governance proposal votes
    mapping(uint256 => Vote) private voteInfo; // mapping of dispute IDs to the details of the vote
    mapping(bytes32 => uint256[]) private voteRounds; // mapping of vote identifier hashes to an array of dispute IDs

    enum VoteResult {
        FAILED,
        PASSED,
        INVALID
    } // status of a potential vote

    // Structs
    struct Dispute {
        bytes32 queryId; // query ID of disputed value
        uint256 timestamp; // timestamp of disputed value
        bytes value; // disputed value
        address disputedReporter; // reporter who submitted the disputed value
        uint256 slashedAmount; // amount of tokens slashed from reporter
    }

    struct Tally {
        uint256 doesSupport; // number of votes in favor
        uint256 against; // number of votes against
        uint256 invalidQuery; // number of votes for invalid
    }

    struct Vote {
        bytes32 identifierHash; // identifier hash of the vote
        uint256 voteRound; // the round of voting on a given dispute or proposal
        uint256 startDate; // timestamp of when vote was initiated
        uint256 blockNumber; // block number of when vote was initiated
        uint256 fee; // fee paid to initiate the vote round
        uint256 tallyDate; // timestamp of when the votes were tallied
        Tally tokenholders; // vote tally of tokenholders
        Tally users; // vote tally of users
        Tally reporters; // vote tally of reporters
        Tally teamMultisig; // vote tally of teamMultisig
        bool executed; // boolean of whether the vote was executed
        VoteResult result; // VoteResult after votes were tallied
        bool isDispute; // boolean of whether the vote is a dispute as opposed to a proposal
        bytes data; // arguments used to execute a proposal
        bytes4 voteFunction; // hash of the function associated with a proposal vote
        address voteAddress; // address of contract to execute function on
        address initiator; // address which initiated dispute/proposal
        mapping(address => bool) voted; // mapping of address to whether or not they voted
    }

    // Events
    event NewDispute(
        uint256 _disputeId,
        bytes32 _queryId,
        uint256 _timestamp,
        address _reporter
    ); // Emitted when a new dispute is opened
    event NewVote(
        address _contract,
        bytes4 _function,
        bytes _data,
        uint256 _disputeId
    ); // Emitted when a new proposal vote is initiated
    event Voted(
        uint256 _disputeId,
        bool _supports,
        address _voter,
        bool _invalidQuery
    ); // Emitted when an address casts their vote
    event VoteExecuted(uint256 _disputeId, VoteResult _result); // Emitted when a vote is executed
    event VoteTallied(
        uint256 _disputeId,
        VoteResult _result,
        address _initiator,
        address _reporter
    ); // Emitted when all casting for a vote is tallied

    /**
     * @dev Initializes contract parameters
     * @param _tellor address of tellor oracle contract to be governed
     * @param _disputeFee base dispute fee
     * @param _teamMultisig address of tellor team multisig, one of four voting
     * stakeholder groups
     */
    constructor(
        address _tellor,
        uint256 _disputeFee,
        address _teamMultisig
    ) {
        tellor = TellorFlex(_tellor);
        token = tellor.token();
        disputeFee = _disputeFee;
        teamMultisig = _teamMultisig;
    }

    /**
     * @dev Helps initialize a dispute by assigning it a disputeId
     * @param _queryId being disputed
     * @param _timestamp being disputed
     */
    function beginDispute(bytes32 _queryId, uint256 _timestamp) external {
        // Ensure value actually exists
        require(
            tellor.getBlockNumberByTimestamp(_queryId, _timestamp) != 0,
            "no value exists at given timestamp"
        );
        bytes32 _hash = keccak256(abi.encodePacked(_queryId, _timestamp));
        // Increment vote count and push new vote round
        voteCount++;
        uint256 _disputeId = voteCount;
        voteRounds[_hash].push(_disputeId);
        // Check if dispute is started within correct time frame
        if (voteRounds[_hash].length > 1) {
            uint256 _prevId = voteRounds[_hash][voteRounds[_hash].length - 2];
            require(
                block.timestamp - voteInfo[_prevId].tallyDate < 1 days,
                "New dispute round must be started within a day"
            ); // Within a day for new round
        } else {
            require(
                block.timestamp - _timestamp < tellor.reportingLock(),
                "Dispute must be started within reporting lock time"
            ); // New dispute within reporting lock
            openDisputesOnId[_queryId]++;
        }
        // Create new vote and dispute
        Vote storage _thisVote = voteInfo[_disputeId];
        Dispute storage _thisDispute = disputeInfo[_disputeId];
        // Initialize dispute information - query ID, timestamp, value, etc.
        _thisDispute.queryId = _queryId;
        _thisDispute.timestamp = _timestamp;
        _thisDispute.value = tellor.retrieveData(_queryId, _timestamp);
        _thisDispute.disputedReporter = tellor.getReporterByTimestamp(
            _queryId,
            _timestamp
        );
        // Initialize vote information - hash, initiator, block number, etc.
        _thisVote.identifierHash = _hash;
        _thisVote.initiator = msg.sender;
        _thisVote.blockNumber = block.number;
        _thisVote.startDate = block.timestamp;
        _thisVote.voteRound = voteRounds[_hash].length;
        _thisVote.isDispute = true;
        // Calculate dispute fee based on number of current vote rounds
        uint256 _fee;
        if (voteRounds[_hash].length == 1) {
            _fee = disputeFee * 2**(openDisputesOnId[_queryId] - 1);
        } else {
            _fee = disputeFee * 2**(voteRounds[_hash].length - 1);
        }
        if (_fee > tellor.stakeAmount()) {
          _fee = tellor.stakeAmount();
        }
        _thisVote.fee = _fee;
        _thisVote.fee = _fee;
        require(
            token.transferFrom(msg.sender, address(this), _fee),
            "Fee must be paid"
        ); // This is the dispute fee. Returned if dispute passes
        if (voteRounds[_hash].length == 1) {
            _thisDispute.slashedAmount = tellor.slashReporter(
                _thisDispute.disputedReporter,
                address(this)
            );
            tellor.removeValue(_queryId, _timestamp);
        } else {
            _thisDispute.slashedAmount = disputeInfo[voteRounds[_hash][0]]
                .slashedAmount;
        }
        emit NewDispute(
            _disputeId,
            _queryId,
            _timestamp,
            _thisDispute.disputedReporter
        );
    }

    /**
     * @dev Executes vote by using result and transferring balance to either
     * initiator or disputed reporter
     * @param _disputeId is the ID of the vote being executed
     */
    function executeVote(uint256 _disputeId) external {
        // Ensure validity of vote ID, vote has been executed, and vote must be tallied
        Vote storage _thisVote = voteInfo[_disputeId];
        require(_disputeId <= voteCount, "Vote ID must be valid");
        require(!_thisVote.executed, "Vote has been executed");
        require(_thisVote.tallyDate > 0, "Vote must be tallied");
        // Ensure vote must be final vote and that time has to be pass (86400 = 24 * 60 * 60 for seconds in a day)
        require(
            voteRounds[_thisVote.identifierHash].length == _thisVote.voteRound,
            "Must be the final vote"
        );
        require(
            block.timestamp - _thisVote.tallyDate >=
                86400 * _thisVote.voteRound,
            "Vote needs to be tallied and time must pass"
        );
        _thisVote.executed = true;
        if (!_thisVote.isDispute) {
            // If vote is not in dispute and passed, execute proper vote function with vote data
            if (_thisVote.result == VoteResult.PASSED) {
                address _destination = _thisVote.voteAddress;
                bool _succ;
                bytes memory _res;
                (_succ, _res) = _destination.call(
                    abi.encodePacked(_thisVote.voteFunction, _thisVote.data)
                ); //When testing _destination.call can require higher gas than the standard. Be sure to increase the gas if it fails.
            }
            emit VoteExecuted(_disputeId, _thisVote.result);
        } else {
            Dispute storage _thisDispute = disputeInfo[_disputeId];
            if (
                voteRounds[_thisVote.identifierHash].length ==
                _thisVote.voteRound
            ) {
                openDisputesOnId[_thisDispute.queryId]--;
            }
            uint256 _i;
            uint256 _voteID;
            if (_thisVote.result == VoteResult.PASSED) {
                // If vote is in dispute and passed, iterate through each vote round and transfer the dispute to initiator
                for (
                    _i = voteRounds[_thisVote.identifierHash].length;
                    _i > 0;
                    _i--
                ) {
                    _voteID = voteRounds[_thisVote.identifierHash][_i - 1];
                    _thisVote = voteInfo[_voteID];
                    // If the first vote round, also make sure to transfer the reporter's slashed stake to the initiator
                    if (_i == 1) {
                        token.transfer(
                            _thisVote.initiator,
                            _thisDispute.slashedAmount
                        );
                    }
                    token.transfer(_thisVote.initiator, _thisVote.fee);
                }
            } else if (_thisVote.result == VoteResult.INVALID) {
                // If vote is in dispute and is invalid, iterate through each vote round and transfer the dispute fee to initiator
                for (
                    _i = voteRounds[_thisVote.identifierHash].length;
                    _i > 0;
                    _i--
                ) {
                    _voteID = voteRounds[_thisVote.identifierHash][_i - 1];
                    _thisVote = voteInfo[_voteID];
                    token.transfer(_thisVote.initiator, _thisVote.fee);
                }
                // Transfer slashed tokens back to disputed reporter
                token.transfer(
                    _thisDispute.disputedReporter,
                    _thisDispute.slashedAmount
                );
            } else if (_thisVote.result == VoteResult.FAILED) {
                // If vote is in dispute and fails, iterate through each vote round and transfer the dispute fee to disputed reporter
                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);
        }
    }

    /**
     * @dev Initializes proposal to change oracle governance address
     * @param _newGovernanceAddress proposed new governance address
     * @param _timestamp used to differentiate proposals. If set to zero, timestamp
     * will automatically be reset to block timestamp
     */
    function proposeChangeGovernanceAddress(
        address _newGovernanceAddress,
        uint256 _timestamp
    ) external {
        _proposeVote(
            address(tellor),
            bytes4(keccak256(bytes("changeGovernanceAddress(address)"))),
            abi.encode(_newGovernanceAddress),
            _timestamp
        );
    }

    /**
     * @dev Initializes proposal to change reporting lock time
     * @param _newReportingLock proposed new reporting lock time
     * @param _timestamp used to differentiate proposals. If set to zero, timestamp
     * will automatically be reset to block timestamp
     */
    function proposeChangeReportingLock(
        uint256 _newReportingLock,
        uint256 _timestamp
    ) external {
        _proposeVote(
            address(tellor),
            bytes4(keccak256(bytes("changeReportingLock(uint256)"))),
            abi.encode(_newReportingLock),
            _timestamp
        );
    }

    /**
     * @dev Initializes proposal to change stake amount
     * @param _newStakeAmount proposed new stake amount
     * @param _timestamp used to differentiate proposals. If set to zero, timestamp
     * will automatically be reset to block timestamp
     */
    function proposeChangeStakeAmount(
        uint256 _newStakeAmount,
        uint256 _timestamp
    ) external {
        _proposeVote(
            address(tellor),
            bytes4(keccak256(bytes("changeStakeAmount(uint256)"))),
            abi.encode(_newStakeAmount),
            _timestamp
        );
    }

    /**
     * @dev Initializes proposal to update user stakeholder list
     * @param _address address whose user status to update
     * @param _isUser true to set address as user, false to remove address from user list
     * @param _timestamp used to differentiate proposals. If set to zero, timestamp
     * will automatically be reset to block timestamp
     */
    function proposeUpdateUserList(
        address _address,
        bool _isUser,
        uint256 _timestamp
    ) external {
        _proposeVote(
            address(this),
            bytes4(keccak256(bytes("updateUserList(address,bool)"))),
            abi.encode(_address, _isUser),
            _timestamp
        );
    }

    /**
     * @dev Tallies the votes and begins the 1 day challenge period
     * @param _disputeId is the dispute id
     */
    function tallyVotes(uint256 _disputeId) external {
        // Ensure vote has not been executed and that vote has not been tallied
        Vote storage _thisVote = voteInfo[_disputeId];
        require(!_thisVote.executed, "Dispute has already been executed");
        require(_thisVote.tallyDate == 0, "Vote has already been tallied");
        require(_disputeId <= voteCount, "Vote does not exist");
        // Determine appropriate vote duration and quorum based on dispute status
        uint256 _duration = 2 days;
        if (!_thisVote.isDispute) {
            _duration = 7 days;
        }
        // Ensure voting is not still open
        require(
            block.timestamp - _thisVote.startDate > _duration,
            "Time for voting has not elapsed"
        );
        // Get total votes from each separate stakeholder group.  This will allow
        // normalization so each group's votes can be combined and compared to
        // determine the vote outcome.
        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;
        // Cannot divide by zero
        if (
            tokenVoteSum * reportersVoteSum * multisigVoteSum * usersVoteSum ==
            0
        ) {
            if (tokenVoteSum == 0) {
                tokenVoteSum++;
            }
            if (reportersVoteSum == 0) {
                reportersVoteSum++;
            }
            if (multisigVoteSum == 0) {
                multisigVoteSum++;
            }
            if (usersVoteSum == 0) {
                usersVoteSum++;
            }
        }
        // Normalize and combine each stakeholder group votes
        uint256 scaledDoesSupport = ((_thisVote.tokenholders.doesSupport *
            10000) / tokenVoteSum) +
            ((_thisVote.reporters.doesSupport * 10000) / reportersVoteSum) +
            ((_thisVote.teamMultisig.doesSupport * 10000) / multisigVoteSum) +
            ((_thisVote.users.doesSupport * 10000) / multisigVoteSum);
        uint256 scaledAgainst = ((_thisVote.tokenholders.against * 10000) /
            tokenVoteSum) +
            ((_thisVote.reporters.against * 10000) / reportersVoteSum) +
            ((_thisVote.teamMultisig.against * 10000) / multisigVoteSum) +
            ((_thisVote.users.against * 10000) / multisigVoteSum);
        uint256 scaledInvalid = ((_thisVote.tokenholders.invalidQuery * 10000) /
            tokenVoteSum) +
            ((_thisVote.reporters.invalidQuery * 10000) / reportersVoteSum) +
            ((_thisVote.teamMultisig.invalidQuery * 10000) / multisigVoteSum) +
            ((_thisVote.users.invalidQuery * 10000) / multisigVoteSum);
        // If there are more invalid votes than for and against, result is invalid
        if (
            scaledInvalid >= scaledDoesSupport &&
            scaledInvalid >= scaledAgainst &&
            _thisVote.isDispute
        ) {
            _thisVote.result = VoteResult.INVALID;
        } else if (scaledDoesSupport > scaledAgainst) {
            // If there are more support votes than against votes, allow the vote to pass
            _thisVote.result = VoteResult.PASSED;
        }
        // If there are more against votes than support votes, the result failed
        else {
            _thisVote.result = VoteResult.FAILED;
        }
        _thisVote.tallyDate = block.timestamp; // Update time vote was tallied
        emit VoteTallied(
            _disputeId,
            _thisVote.result,
            _thisVote.initiator,
            disputeInfo[_disputeId].disputedReporter
        );
    }

    /**
     * @dev Changes address's status as user. Can only be called by this contract
     * through a proposeUpdateUserList proposal
     * @param _address address whose user status to update
     * @param _isUser true to set address as user, false to remove address from user list
     */
    function updateUserList(address _address, bool _isUser) external {
        require(
            msg.sender == address(this),
            "Only governance can update user list"
        );
        users[_address] = _isUser;
    }

    /**
     * @dev Enables the sender address to cast a vote
     * @param _disputeId is the ID of the vote
     * @param _supports is the address's vote: whether or not they support or are against
     * @param _invalidQuery is whether or not the dispute is valid
     */
    function vote(
        uint256 _disputeId,
        bool _supports,
        bool _invalidQuery
    ) external {
        // Ensure that dispute has not been executed and that vote does not exist and is not tallied
        require(_disputeId <= voteCount, "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");
        // Update voting status and increment total queries for support, invalid, or against based on vote
        _thisVote.voted[msg.sender] = true;
        uint256 voteWeight = token.balanceOf(msg.sender);
        (, uint256 stakedBalance, uint256 lockedBalance, , ) = tellor
            .getStakerInfo(msg.sender);
        voteWeight += stakedBalance + lockedBalance;
        if (_thisVote.isDispute && _invalidQuery) {
            if (voteWeight > 0) {
                _thisVote.tokenholders.invalidQuery += voteWeight;
            }
            voteWeight = tellor.getReportsSubmittedByAddress(msg.sender);
            if (voteWeight > 0) {
                _thisVote.reporters.invalidQuery += voteWeight;
            }
            if (users[msg.sender]) {
                _thisVote.users.invalidQuery += 1;
            }
            if (msg.sender == teamMultisig) {
                _thisVote.teamMultisig.invalidQuery += 1;
            }
        } else if (_supports) {
            if (voteWeight > 0) {
                _thisVote.tokenholders.doesSupport += voteWeight;
            }
            voteWeight = tellor.getReportsSubmittedByAddress(msg.sender);
            if (voteWeight > 0) {
                _thisVote.reporters.doesSupport += voteWeight;
            }
            if (users[msg.sender]) {
                _thisVote.users.doesSupport += 1;
            }
            if (msg.sender == teamMultisig) {
                _thisVote.teamMultisig.doesSupport += 1;
            }
        } else {
            if (voteWeight > 0) {
                _thisVote.tokenholders.against += voteWeight;
            }
            voteWeight = tellor.getReportsSubmittedByAddress(msg.sender);
            if (voteWeight > 0) {
                _thisVote.reporters.against += voteWeight;
            }
            if (users[msg.sender]) {
                _thisVote.users.against += 1;
            }
            if (msg.sender == teamMultisig) {
                _thisVote.teamMultisig.against += 1;
            }
        }
        emit Voted(_disputeId, _supports, msg.sender, _invalidQuery);
    }

    // Getters
    /**
     * @dev Determines if an address voted for a specific vote
     * @param _disputeId is the ID of the vote
     * @param _voter is the address of the voter to check for
     * @return bool of whether or note the address voted for the specific vote
     */
    function didVote(uint256 _disputeId, address _voter)
        external
        view
        returns (bool)
    {
        return voteInfo[_disputeId].voted[_voter];
    }

    /**
     * @dev Returns info on a dispute for a given ID
     * @param _disputeId is the ID of a specific dispute
     * @return bytes32 of the data ID of the dispute
     * @return uint256 of the timestamp of the dispute
     * @return bytes memory of the value being disputed
     * @return address of the reporter being disputed
     */
    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);
    }

    /**
     * @dev Returns the number of open disputes for a specific query ID
     * @param _queryId is the ID of a specific data feed
     * @return uint256 of the number of open disputes for the query ID
     */
    function getOpenDisputesOnId(bytes32 _queryId)
        external
        view
        returns (uint256)
    {
        return openDisputesOnId[_queryId];
    }

    /**
     * @dev Returns the total number of votes
     * @return uint256 of the total number of votes
     */
    function getVoteCount() external view returns (uint256) {
        return voteCount;
    }

    /**
     * @dev Returns info on a vote for a given vote ID
     * @param _disputeId is the ID of a specific vote
     * @return bytes32 identifier hash of the vote
     * @return uint256[8] memory of the pertinent round info (vote rounds, start date, fee, etc.)
     * @return bool[2] memory of both whether or not the vote was executed and is dispute
     * @return VoteResult result of the vote
     * @return bytes memory of the argument data of a proposal vote
     * @return bytes4 of the function selector proposed to be called
     * @return address[2] memory of the Tellor system contract address and vote initiator
     */
    function getVoteInfo(uint256 _disputeId)
        external
        view
        returns (
            bytes32,
            uint256[17] memory,
            bool[2] memory,
            VoteResult,
            bytes memory,
            bytes4,
            address[2] memory
        )
    {
        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.isDispute],
            _v.result,
            _v.data,
            _v.voteFunction,
            [_v.voteAddress, _v.initiator]
        );
    }

    /**
     * @dev Returns an array of voting rounds for a given vote
     * @param _hash is the identifier hash for a vote
     * @return uint256[] memory dispute IDs of the vote rounds
     */
    function getVoteRounds(bytes32 _hash)
        external
        view
        returns (uint256[] memory)
    {
        return voteRounds[_hash];
    }

    /**
     * @dev Returns boolean value for whether a given address is set as a user with
     * voting rights
     * @param _address address of potential user
     * @return bool whether or not the address is set as a user
     */
    function isUser(address _address) external view returns (bool) {
        return users[_address];
    }

    // Internal
    /**
     * @dev Proposes a vote for an associated Tellor contract and function, and defines the properties of the vote
     * @param _contract is the Tellor contract to propose a vote for -> used to calculate identifier hash
     * @param _function is the Tellor function to propose a vote for -> used to calculate identifier hash
     * @param _data is the function argument data associated with the vote proposal -> used to calculate identifier hash
     * @param _timestamp is the timestamp associated with the vote -> used to calculate identifier hash
     */
    function _proposeVote(
        address _contract,
        bytes4 _function,
        bytes memory _data,
        uint256 _timestamp
    ) internal {
        // Update vote count, vote ID, current vote, and timestamp
        voteCount++;
        uint256 _disputeId = voteCount;
        Vote storage _thisVote = voteInfo[_disputeId];
        if (_timestamp == 0) {
            _timestamp = block.timestamp;
        }
        // Calculate vote identifier hash and push to vote rounds
        bytes32 _hash = keccak256(
            abi.encodePacked(_contract, _function, _data, _timestamp)
        );
        voteRounds[_hash].push(_disputeId);
        // Ensure new dispute round started within a day
        if (voteRounds[_hash].length > 1) {
            uint256 _prevId = voteRounds[_hash][voteRounds[_hash].length - 2];
            require(
                block.timestamp - voteInfo[_prevId].tallyDate < 1 days,
                "New dispute round must be started within a day"
            ); // 1 day for new disputes
        }
        // Calculate fee to propose vote. Starts as just 10 tokens flat, doubles with each round
        uint256 _fee = 10e18 * 2**(voteRounds[_hash].length - 1);
        require(
            token.transferFrom(msg.sender, address(this), _fee),
            "Fee must be paid"
        );
        // Update information on vote -- hash, vote round, start date, block number, fee, etc.
        _thisVote.identifierHash = _hash;
        _thisVote.voteRound = voteRounds[_hash].length;
        _thisVote.startDate = block.timestamp;
        _thisVote.blockNumber = block.number;
        _thisVote.fee = _fee;
        _thisVote.data = _data;
        _thisVote.voteFunction = _function;
        _thisVote.voteAddress = _contract;
        _thisVote.initiator = msg.sender;
        emit NewVote(_contract, _function, _data, _disputeId);
    }
}

File 2 of 3 : TellorFlex.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

import "./interfaces/IERC20.sol";

/**
 @author Tellor Inc.
 @title TellorFlex
 @dev This is a streamlined Tellor 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 TellorFlex {
    IERC20 public token;
    address public governance;
    uint256 public stakeAmount; //amount required to be a staker
    uint256 public totalStakeAmount; //total amount of tokens locked in contract (via stake)
    uint256 public reportingLock; // base amount of time before a reporter is able to submit a value again
    uint256 public timeOfLastNewValue = block.timestamp; // time of the last new submitted value, originally set to the block timestamp
    mapping(bytes32 => Report) private reports; // mapping of query IDs to a report
    mapping(address => StakeInfo) stakerDetails; //mapping from a persons address to their staking info

    // Structs
    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
    }

    struct StakeInfo {
        uint256 startDate; //stake start date
        uint256 stakedBalance; // staked balance
        uint256 lockedBalance; // amount locked for withdrawal
        uint256 reporterLastTimestamp; // timestamp of reporter's last reported value
        uint256 reportsSubmitted; // total number of reports submitted by reporter
        mapping(bytes32 => uint256) reportsSubmittedByQueryId;
    }

    // Events
    event NewGovernanceAddress(address _newGovernanceAddress);
    event NewReport(
        bytes32 _queryId,
        uint256 _time,
        bytes _value,
        uint256 _nonce,
        bytes _queryData,
        address _reporter
    );
    event NewReportingLock(uint256 _newReportingLock);
    event NewStakeAmount(uint256 _newStakeAmount);
    event NewStaker(address _staker, uint256 _amount);
    event ReporterSlashed(
        address _reporter,
        address _recipient,
        uint256 _slashAmount
    );
    event StakeWithdrawRequested(address _staker, uint256 _amount);
    event StakeWithdrawn(address _staker);
    event ValueRemoved(bytes32 _queryId, uint256 _timestamp);

    /**
     * @dev Initializes system parameters
     * @param _token address of token used for staking
     * @param _governance address which controls system
     * @param _stakeAmount amount of token needed to report oracle values
     * @param _reportingLock base amount of time (seconds) before reporter is able to report again
     */
    constructor(
        address _token,
        address _governance,
        uint256 _stakeAmount,
        uint256 _reportingLock
    ) {
        require(_token != address(0), "must set token address");
        require(_governance != address(0), "must set governance address");
        token = IERC20(_token);
        governance = _governance;
        stakeAmount = _stakeAmount;
        reportingLock = _reportingLock;
    }

    /**
     * @dev Changes governance address
     * @param _newGovernanceAddress new governance address
     */
    function changeGovernanceAddress(address _newGovernanceAddress) external {
        require(msg.sender == governance, "caller must be governance address");
        require(
            _newGovernanceAddress != address(0),
            "must set governance address"
        );
        governance = _newGovernanceAddress;
        emit NewGovernanceAddress(_newGovernanceAddress);
    }

    /**
     * @dev Changes base amount of time (seconds) before reporter is allowed to report again
     * @param _newReportingLock new reporter lock time in seconds
     */
    function changeReportingLock(uint256 _newReportingLock) external {
        require(msg.sender == governance, "caller must be governance address");
        require(
            _newReportingLock > 0,
            "reporting lock must be greater than zero"
        );
        reportingLock = _newReportingLock;
        emit NewReportingLock(_newReportingLock);
    }

    /**
     * @dev Changes amount of token stake required to report values
     * @param _newStakeAmount new reporter stake amount
     */
    function changeStakeAmount(uint256 _newStakeAmount) external {
        require(msg.sender == governance, "caller must be governance address");
        require(_newStakeAmount > 0, "stake amount must be greater than zero");
        stakeAmount = _newStakeAmount;
        emit NewStakeAmount(_newStakeAmount);
    }

    /**
     * @dev Allows a reporter to submit stake
     * @param _amount amount of tokens to stake
     */
    function depositStake(uint256 _amount) external {
        StakeInfo storage _staker = stakerDetails[msg.sender];
        if (_staker.lockedBalance > 0) {
            if (_staker.lockedBalance >= _amount) {
                _staker.lockedBalance -= _amount;
            } else {
                require(
                    token.transferFrom(
                        msg.sender,
                        address(this),
                        _amount - _staker.lockedBalance
                    )
                );
                _staker.lockedBalance = 0;
            }
        } else {
            require(token.transferFrom(msg.sender, address(this), _amount));
        }
        _staker.startDate = block.timestamp; // This resets their stake start date to now
        _staker.stakedBalance += _amount;
        totalStakeAmount += _amount;
        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 {
        require(msg.sender == governance, "caller must be governance address");
        Report storage rep = reports[_queryId];
        uint256 _index = rep.timestampIndex[_timestamp];
        require(_timestamp == rep.timestamps[_index], "invalid timestamp");
        // Shift all timestamps back to reflect deletion of value
        for (uint256 _i = _index; _i < rep.timestamps.length - 1; _i++) {
            rep.timestamps[_i] = rep.timestamps[_i + 1];
            rep.timestampIndex[rep.timestamps[_i]] -= 1;
        }
        // Delete and reset timestamp and value
        delete rep.timestamps[rep.timestamps.length - 1];
        rep.timestamps.pop();
        rep.valueByTimestamp[_timestamp] = "";
        rep.timestampIndex[_timestamp] = 0;
        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"
        );
        _staker.startDate = block.timestamp;
        _staker.lockedBalance += _amount;
        _staker.stakedBalance -= _amount;
        totalStakeAmount -= _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 uint256 amount of token slashed and sent to recipient address
     */
    function slashReporter(address _reporter, address _recipient)
        external
        returns (uint256)
    {
        require(msg.sender == governance, "only governance can slash reporter");
        StakeInfo storage _staker = stakerDetails[_reporter];
        require(
            _staker.stakedBalance + _staker.lockedBalance > 0,
            "zero staker balance"
        );
        uint256 _slashAmount;
        if (_staker.lockedBalance >= stakeAmount) {
            _slashAmount = stakeAmount;
            _staker.lockedBalance -= stakeAmount;
        } else if (
            _staker.lockedBalance + _staker.stakedBalance >= stakeAmount
        ) {
            _slashAmount = stakeAmount;
            _staker.stakedBalance -= stakeAmount - _staker.lockedBalance;
            totalStakeAmount -= stakeAmount - _staker.lockedBalance;
            _staker.lockedBalance = 0;
        } else {
            _slashAmount = _staker.stakedBalance + _staker.lockedBalance;
            totalStakeAmount -= _staker.stakedBalance;
            _staker.stakedBalance = 0;
            _staker.lockedBalance = 0;
        }
        token.transfer(_recipient, _slashAmount);
        emit ReporterSlashed(_reporter, _recipient, _slashAmount);
        return (_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 memory _queryData
    ) external {
        Report storage rep = reports[_queryId];
        require(
            _nonce == rep.timestamps.length || _nonce == 0,
            "nonce must match timestamp index"
        );
        StakeInfo storage _staker = stakerDetails[msg.sender];
        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) || uint256(_queryId) <= 100,
            "id must be hash of bytes data"
        );
        _staker.reporterLastTimestamp = block.timestamp;
        // Checks for no double reporting of timestamps
        require(
            rep.reporterByTimestamp[block.timestamp] == address(0),
            "timestamp already reported for"
        );
        // Update number of timestamps, value for given timestamp, and reporter for timestamp
        rep.timestampIndex[block.timestamp] = rep.timestamps.length;
        rep.timestamps.push(block.timestamp);
        rep.timestampToBlockNum[block.timestamp] = block.number;
        rep.valueByTimestamp[block.timestamp] = _value;
        rep.reporterByTimestamp[block.timestamp] = msg.sender;
        // 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 Withdraws a reporter's stake
     */
    function withdrawStake() external {
        StakeInfo storage _s = stakerDetails[msg.sender];
        // Ensure reporter is locked and that enough time has passed
        require(block.timestamp - _s.startDate >= 7 days, "7 days didn't pass");
        require(_s.lockedBalance > 0, "reporter not locked for withdrawal");
        token.transfer(msg.sender, _s.lockedBalance);
        _s.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 bytes memory of the current value of data
     */
    function getCurrentValue(bytes32 _queryId)
        external
        view
        returns (bytes memory)
    {
        return
            reports[_queryId].valueByTimestamp[
                reports[_queryId].timestamps[
                    reports[_queryId].timestamps.length - 1
                ]
            ];
    }

    /**
     * @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)
        external
        view
        returns (uint256)
    {
        return reports[_queryId].timestamps.length;
    }

    /**
     * @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)
    {
        bool _wasRemoved = reports[_queryId].timestampIndex[_timestamp] == 0 &&
            keccak256(reports[_queryId].valueByTimestamp[_timestamp]) ==
            keccak256(bytes("")) &&
            reports[_queryId].reporterByTimestamp[_timestamp] != address(0);
        return (reports[_queryId].reporterByTimestamp[_timestamp], _wasRemoved);
    }

    /**
     * @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 of 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 of 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 Allows users to retrieve all information about a staker
     * @param _staker address of staker inquiring about
     * @return uint startDate of staking
     * @return uint current amount staked
     * @return uint current amount locked for withdrawal
     * @return uint reporter's last reported timestamp
     * @return uint total number of reports submitted by reporter
     */
    function getStakerInfo(address _staker)
        external
        view
        returns (
            uint256,
            uint256,
            uint256,
            uint256,
            uint256
        )
    {
        return (
            stakerDetails[_staker].startDate,
            stakerDetails[_staker].stakedBalance,
            stakerDetails[_staker].lockedBalance,
            stakerDetails[_staker].reporterLastTimestamp,
            stakerDetails[_staker].reportsSubmitted
        );
    }

    /**
     * @dev Returns the timestamp for the last value of any ID from the oracle
     * @return uint256 of 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)
        external
        view
        returns (uint256)
    {
        return reports[_queryId].timestamps[_index];
    }

    /**
     * @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 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)
        external
        view
        returns (bytes memory)
    {
        return reports[_queryId].valueByTimestamp[_timestamp];
    }
}

File 3 of 3 : IERC20.sol
// SPDX-License-Identifier: MIT
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);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 300
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_tellor","type":"address"},{"internalType":"uint256","name":"_disputeFee","type":"uint256"},{"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":"address","name":"_contract","type":"address"},{"indexed":false,"internalType":"bytes4","name":"_function","type":"bytes4"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"NewVote","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":[{"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":[],"name":"disputeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_disputeId","type":"uint256"}],"name":"executeVote","outputs":[],"stateMutability":"nonpayable","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":"bytes32","name":"_queryId","type":"bytes32"}],"name":"getOpenDisputesOnId","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[2]","name":"","type":"bool[2]"},{"internalType":"enum Governance.VoteResult","name":"","type":"uint8"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"address[2]","name":"","type":"address[2]"}],"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":"_address","type":"address"}],"name":"isUser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernanceAddress","type":"address"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"proposeChangeGovernanceAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newReportingLock","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"proposeChangeReportingLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newStakeAmount","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"proposeChangeStakeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_isUser","type":"bool"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"proposeUpdateUserList","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 TellorFlex","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_isUser","type":"bool"}],"name":"updateUserList","outputs":[],"stateMutability":"nonpayable","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"}]

60806040523480156200001157600080fd5b50604051620034e3380380620034e38339810160408190526200003491620000fc565b600080546001600160a01b0319166001600160a01b03851690811790915560408051637e062a3560e11b8152905163fc0c546a91600480820192602092909190829003018186803b1580156200008957600080fd5b505afa1580156200009e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c4919062000143565b600180546001600160a01b03199081166001600160a01b03938416179091556004939093556002805490931691161790555062000182565b60008060006060848603121562000111578283fd5b83516200011e8162000169565b602085015160408601519194509250620001388162000169565b809150509250925092565b60006020828403121562000155578081fd5b8151620001628162000169565b9392505050565b6001600160a01b03811681146200017f57600080fd5b50565b61335180620001926000396000f3fe608060405234801561001057600080fd5b50600436106101475760003560e01c8063a3cb1604116100c8578063dbc0c0851161008c578063ec36902511610066578063ec36902514610340578063f98a4eca14610353578063fc0c546a1461036657610147565b8063dbc0c08514610312578063df133bca14610325578063e7b3387c1461033857610147565b8063a3cb16041461029d578063a7c438bc146102b0578063b9ce896b146102ed578063c6384071146102f6578063d3b5e361146102ff57610147565b80634209fff11161010f5780634209fff1146101f25780634ac6eb7c1461022e5780634d318b0e146102415780636169c308146102545780638d8242731461027757610147565b80630e1596ef1461014c5780631959ad5b1461017f5780631f379acc146101aa57806321440a77146101bf578063248638e5146101d2575b600080fd5b61016c61015a366004612b67565b60009081526006602052604090205490565b6040519081526020015b60405180910390f35b600054610192906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6101bd6101b8366004612b7f565b610379565b005b6101bd6101cd366004612b7f565b610c3e565b6101e56101e0366004612b67565b610cc8565b6040516101769190612ee9565b61021e610200366004612a69565b6001600160a01b031660009081526007602052604090205460ff1690565b6040519015158152602001610176565b6101bd61023c366004612b20565b610d2a565b6101bd61024f366004612b67565b610db0565b610267610262366004612b67565b61130c565b6040516101769493929190612fdd565b61028a610285366004612b67565b6113e0565b6040516101769796959493929190612f2d565b6101bd6102ab366004612aa8565b6115e2565b61021e6102be366004612c61565b60008281526008602090815260408083206001600160a01b038516845260160190915290205460ff1692915050565b61016c60045481565b61016c60035481565b6101bd61030d366004612ae0565b611668565b600254610192906001600160a01b031681565b6101bd610333366004612c85565b6116ef565b60035461016c565b6101bd61034e366004612b7f565b611d1e565b6101bd610361366004612b67565b611d93565b600154610192906001600160a01b031681565b600054604051630935408d60e41b815260048101849052602481018390526001600160a01b039091169063935408d09060440160206040518083038186803b1580156103c457600080fd5b505afa1580156103d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fc9190612c49565b6104585760405162461bcd60e51b815260206004820152602260248201527f6e6f2076616c75652065786973747320617420676976656e2074696d6573746160448201526106d760f41b60648201526084015b60405180910390fd5b6040805160208082018590528183018490528251808303840181526060909201909252805191012060038054906000610490836132ae565b90915550506003546000828152600960209081526040822080546001818101835582855292842001849055918490529054111561055757600082815260096020526040812080546104e390600290613219565b8154811061050157634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426105349190613219565b106105515760405162461bcd60e51b815260040161044f90613016565b5061066d565b60008054906101000a90046001600160a01b03166001600160a01b0316633321fc416040518163ffffffff1660e01b815260040160206040518083038186803b1580156105a357600080fd5b505afa1580156105b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105db9190612c49565b6105e58442613219565b1061064d5760405162461bcd60e51b815260206004820152603260248201527f44697370757465206d75737420626520737461727465642077697468696e207260448201527165706f7274696e67206c6f636b2074696d6560701b606482015260840161044f565b6000848152600660205260408120805491610667836132ae565b91905055505b60008181526008602090815260408083206005909252808320878155600181018790559254905163c5958af960e01b815260048101889052602481018790529192916001600160a01b039091169063c5958af99060440160006040518083038186803b1580156106dc57600080fd5b505afa1580156106f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107189190810190612ba0565b805161072e916002840191602090910190612993565b5060005460405163703e2a4360e11b815260048101889052602481018790526001600160a01b039091169063e07c54869060440160206040518083038186803b15801561077a57600080fd5b505afa15801561078e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b29190612a8c565b600380830180546001600160a01b03939093166001600160a01b0319938416179055858455601584018054909216331790915543908301554260028301556000848152600960205260408120805460018581019190915560128501805462ff00001916620100001790559054141561085e5760008781526006602052604090205461083f90600190613219565b61084a90600261312c565b60045461085791906131fa565b9050610894565b60008581526009602052604090205461087990600190613219565b61088490600261312c565b60045461089191906131fa565b90505b60008054906101000a90046001600160a01b03166001600160a01b03166360c7dc476040518163ffffffff1660e01b815260040160206040518083038186803b1580156108e057600080fd5b505afa1580156108f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109189190612c49565b8111156109a65760008054906101000a90046001600160a01b03166001600160a01b03166360c7dc476040518163ffffffff1660e01b815260040160206040518083038186803b15801561096b57600080fd5b505afa15801561097f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a39190612c49565b90505b60048381018290556001546040516323b872dd60e01b81523392810192909252306024830152604482018390526001600160a01b0316906323b872dd90606401602060405180830381600087803b158015610a0057600080fd5b505af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190612b4b565b610a775760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b60008581526009602052604090205460011415610b8757600054600383015460405163137f0a8d60e21b81526001600160a01b039182166004820152306024820152911690634dfc2a3490604401602060405180830381600087803b158015610adf57600080fd5b505af1158015610af3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b179190612c49565b6004838101919091556000546040516316d7b73f60e21b8152918201899052602482018890526001600160a01b031690635b5edcfc90604401600060405180830381600087803b158015610b6a57600080fd5b505af1158015610b7e573d6000803e3d6000fd5b50505050610bde565b6000858152600960205260408120805460059291908290610bb857634e487b7160e01b600052603260045260246000fd5b906000526020600020015481526020019081526020016000206004015482600401819055505b600382015460408051868152602081018a90529081018890526001600160a01b0390911660608201527f12b7317353cd7caa8eae8057464e3de356c1429d814fb3421797eccb19043044906080015b60405180910390a150505050505050565b600054604080518082018252601a81527f6368616e67655374616b65416d6f756e742875696e74323536290000000000006020918201528151908101859052610cc4926001600160a01b0316917fca79b5a978ea700f37e874524ca56caf88471abdb2cff892cab3e91ff005e0a191015b6040516020818303038152906040528461269c565b5050565b600081815260096020908152604091829020805483518184028101840190945280845260609392830182828015610d1e57602002820191906000526020600020905b815481526020019060010190808311610d0a575b50505050509050919050565b60005460408051808201825260208082527f6368616e6765476f7665726e616e636541646472657373286164647265737329918101919091529051610cc4926001600160a01b0316917f0636769e56486090c573831c9de80fac4458ca89aa37a2afff688bfcbc1ad71191610caf918791016001600160a01b0391909116815260200190565b6000818152600860205260409020601281015460ff1615610e1d5760405162461bcd60e51b815260206004820152602160248201527f446973707574652068617320616c7265616479206265656e20657865637574656044820152601960fa1b606482015260840161044f565b600581015415610e6f5760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b600354821115610eb75760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60128101546202a3009062010000900460ff16610ed4575062093a805b80826002015442610ee59190613219565b11610f325760405162461bcd60e51b815260206004820152601f60248201527f54696d6520666f7220766f74696e6720686173206e6f7420656c617073656400604482015260640161044f565b60088201546007830154600684015460009291610f4e916130ae565b610f5891906130ae565b600e840154600d850154600c860154929350600092610f7791906130ae565b610f8191906130ae565b60118501546010860154600f870154929350600092610fa091906130ae565b610faa91906130ae565b600b860154600a8701546009880154929350600092610fc991906130ae565b610fd391906130ae565b90508082610fe185876131fa565b610feb91906131fa565b610ff591906131fa565b611045578361100c5783611008816132ae565b9450505b8261101f578261101b816132ae565b9350505b81611032578161102e816132ae565b9250505b806110455780611041816132ae565b9150505b6009860154600090839061105b906127106131fa565b61106591906130c6565b600f8801548490611078906127106131fa565b61108291906130c6565b600c8901548690611095906127106131fa565b61109f91906130c6565b60068a015488906110b2906127106131fa565b6110bc91906130c6565b6110c691906130ae565b6110d091906130ae565b6110da91906130ae565b905060008388600901600101546127106110f491906131fa565b6110fe91906130c6565b60108901548590611111906127106131fa565b61111b91906130c6565b600d8a0154879061112e906127106131fa565b61113891906130c6565b60078b0154899061114b906127106131fa565b61115591906130c6565b61115f91906130ae565b61116991906130ae565b61117391906130ae565b9050600084896009016002015461271061118d91906131fa565b61119791906130c6565b60118a015486906111aa906127106131fa565b6111b491906130c6565b600e8b015488906111c7906127106131fa565b6111d191906130c6565b60088c01548a906111e4906127106131fa565b6111ee91906130c6565b6111f891906130ae565b61120291906130ae565b61120c91906130ae565b905082811015801561121e5750818110155b80156112345750601289015462010000900460ff165b15611257576012890180546002919061ff001916610100835b0217905550611285565b81831115611277576012890180546001919061ff0019166101008361124d565b60128901805461ff00191690555b4260058a81019190915560128a015460158b015460008d81526020939093526040928390206003015492517fa2d4e500801849d40ad00f0f12ba92a5263f83ec68946e647be95cfbe581c7b6936112f8938f9361010090910460ff16926001600160a01b03918216929190911690613078565b60405180910390a150505050505050505050565b6000818152600560205260408120805460018201546003830154600284018054869560609587959194909391926001600160a01b0390911690829061135090613273565b80601f016020809104026020016040519081016040528092919081815260200182805461137c90613273565b80156113c95780601f1061139e576101008083540402835291602001916113c9565b820191906000526020600020905b8154815290600101906020018083116113ac57829003601f168201915b505050505091509450945094509450509193509193565b60006113ea612a17565b6113f2612a36565b600060606000611400612a36565b6000888152600860208181526040928390208054845161022081018652600183015481526002830154818501526003830154818701526004830154606082015260058301546080820152600683015460a0820152600783015460c08201529382015460e080860191909152600983015461010080870191909152600a840154610120870152600b840154610140870152600c840154610160870152600d840154610180870152600e8401546101a0870152600f8401546101c087015260108401546101e0870152601184015461020087015286518088018852601285015460ff80821615158352620100008204811615158389015260148701548a51808c01909b526001600160a01b03640100000000820481168c52601589015416988b0198909852601387018054979a969998939794909204169490939190911b91839061154890613273565b80601f016020809104026020016040519081016040528092919081815260200182805461157490613273565b80156115c15780601f10611596576101008083540402835291602001916115c1565b820191906000526020600020905b8154815290600101906020018083116115a457829003601f168201915b50505050509250975097509750975097509750975050919395979092949650565b33301461163d5760405162461bcd60e51b8152602060048201526024808201527f4f6e6c7920676f7665726e616e63652063616e207570646174652075736572206044820152631b1a5cdd60e21b606482015260840161044f565b6001600160a01b03919091166000908152600760205260409020805460ff1916911515919091179055565b604080518082018252601c81527f757064617465557365724c69737428616464726573732c626f6f6c290000000060209182015290516116ea9130917fa3cb1604d428d5b2db415cab07e750952a0559e3ea14fc2ad01393fcccac6aee91610caf9188918891016001600160a01b039290921682521515602082015260400190565b505050565b6003548311156117375760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60008381526008602052604090206005810154156117975760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b33600090815260168201602052604090205460ff16156117f95760405162461bcd60e51b815260206004820152601860248201527f53656e6465722068617320616c726561647920766f7465640000000000000000604482015260640161044f565b336000818152601683016020526040808220805460ff191660019081179091555490516370a0823160e01b8152600481019390935290916001600160a01b03909116906370a082319060240160206040518083038186803b15801561185d57600080fd5b505afa158015611871573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118959190612c49565b60008054604051630733bdef60e41b8152336004820152929350909182916001600160a01b03169063733bdef09060240160a06040518083038186803b1580156118de57600080fd5b505afa1580156118f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119169190612cc6565b50509250925050808261192991906130ae565b61193390846130ae565b601285015490935062010000900460ff16801561194d5750845b15611a81578215611975578284600601600201600082825461196f91906130ae565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b1580156119b857600080fd5b505afa1580156119cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f09190612c49565b92508215611a15578284600c016002016000828254611a0f91906130ae565b90915550505b3360009081526007602052604090205460ff1615611a4b576001846009016002016000828254611a4591906130ae565b90915550505b6002546001600160a01b0316331415611a7c57600184600f016002016000828254611a7691906130ae565b90915550505b611cd5565b8515611bab578215611aaa5782846006016000016000828254611aa491906130ae565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b259190612c49565b92508215611b4a578284600c016000016000828254611b4491906130ae565b90915550505b3360009081526007602052604090205460ff1615611b80576001846009016000016000828254611b7a91906130ae565b90915550505b6002546001600160a01b0316331415611a7c57600184600f016000016000828254611a7691906130ae565b8215611bce5782846006016001016000828254611bc891906130ae565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b158015611c1157600080fd5b505afa158015611c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c499190612c49565b92508215611c6e578284600c016001016000828254611c6891906130ae565b90915550505b3360009081526007602052604090205460ff1615611ca4576001846009016001016000828254611c9e91906130ae565b90915550505b6002546001600160a01b0316331415611cd557600184600f016001016000828254611ccf91906130ae565b90915550505b604080518881528715156020820152339181019190915285151560608201527fbe6f1c58cc15c8e86d6f0ef23c5a30eb33319af3b57f6b7d9b56ccfa87696b8490608001610c2d565b600054604080518082018252601c81527f6368616e67655265706f7274696e674c6f636b2875696e7432353629000000006020918201528151908101859052610cc4926001600160a01b0316917f5d183cfa1084f72f49f0f81fe5d34bf9533a659ae85960ce554cbcf02302ca309101610caf565b6000818152600860205260409020600354821115611df35760405162461bcd60e51b815260206004820152601560248201527f566f7465204944206d7573742062652076616c69640000000000000000000000604482015260640161044f565b601281015460ff1615611e485760405162461bcd60e51b815260206004820152601660248201527f566f746520686173206265656e20657865637574656400000000000000000000604482015260640161044f565b6000816005015411611e9c5760405162461bcd60e51b815260206004820152601460248201527f566f7465206d7573742062652074616c6c696564000000000000000000000000604482015260640161044f565b6001810154815460009081526009602052604090205414611eff5760405162461bcd60e51b815260206004820152601660248201527f4d757374206265207468652066696e616c20766f746500000000000000000000604482015260640161044f565b6001810154611f1190620151806131fa565b6005820154611f209042613219565b1015611f825760405162461bcd60e51b815260206004820152602b60248201527f566f7465206e6565647320746f2062652074616c6c69656420616e642074696d60448201526a65206d757374207061737360a81b606482015260840161044f565b60128101805460ff19166001179081905562010000900460ff166120b95760016012820154610100900460ff166002811115611fce57634e487b7160e01b600052602160045260246000fd5b141561206e5760148101546040516001600160a01b0364010000000083041691600091606091849161200b9160e01b906013880190602001612dd7565b60408051601f198184030181529082905261202591612e8b565b6000604051808303816000865af19150503d8060008114612062576040519150601f19603f3d011682016040523d82523d6000602084013e612067565b606091505b5050505050505b60128101546040517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da4916120ac918591610100900460ff1690613064565b60405180910390a1610cc4565b60008281526005602090815260408083206001850154855485526009909352922054141561210357805460009081526006602052604081208054916120fd8361325c565b91905055505b60008060016012850154610100900460ff16600281111561213457634e487b7160e01b600052602160045260246000fd5b14156122f257835460009081526009602052604090205491505b81156122ed578354600090815260096020526040902061216f600184613219565b8154811061218d57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050600860008281526020019081526020016000209350816001141561224a57600154601585015460048581015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561221057600080fd5b505af1158015612224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122489190612b4b565b505b600154601585015460048087015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b1580156122a257600080fd5b505af11580156122b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122da9190612b4b565b50816122e58161325c565b92505061214e565b612641565b60026012850154610100900460ff16600281111561232057634e487b7160e01b600052602160045260246000fd5b14156124d657835460009081526009602052604090205491505b8115612440578354600090815260096020526040902061235b600184613219565b8154811061237957634e487b7160e01b600052603260045260246000fd5b60009182526020808320919091015480835260089091526040918290206001546015820154600480840154955163a9059cbb60e01b81526001600160a01b03928316918101919091526024810195909552919750919350169063a9059cbb90604401602060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242d9190612b4b565b50816124388161325c565b92505061233a565b600154600384015460048086015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561249857600080fd5b505af11580156124ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d09190612b4b565b50612641565b60006012850154610100900460ff16600281111561250457634e487b7160e01b600052602160045260246000fd5b141561264157835460009081526009602052604081205492505b82156125a3578454600090815260096020526040902061253f600185613219565b8154811061255d57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154915060086000838152602001908152602001600020945084600401548161258f91906130ae565b90508261259b8161325c565b93505061251e565b60048401546125b290826130ae565b600154600386015460405163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350169063a9059cbb90604401602060405180830381600087803b15801561260657600080fd5b505af115801561261a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263e9190612b4b565b50505b600085815260086020526040908190206012015490517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da49161268d918891610100900460ff1690613064565b60405180910390a15050505050565b600380549060006126ac836132ae565b90915550506003546000818152600860205260409020826126cb574292505b6000868686866040516020016126e49493929190612d85565b60408051601f1981840301815291815281516020928301206000818152600984529182208054600181810183558285529484200187905591819052905490925011156127b6576000818152600960205260408120805461274690600290613219565b8154811061276457634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426127979190613219565b106127b45760405162461bcd60e51b815260040161044f90613016565b505b6000818152600960205260408120546127d190600190613219565b6127dc90600261312c565b6127ee90678ac7230489e800006131fa565b6001546040516323b872dd60e01b8152336004820152306024820152604481018390529192506001600160a01b0316906323b872dd90606401602060405180830381600087803b15801561284157600080fd5b505af1158015612855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128799190612b4b565b6128b85760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b81835560008281526009602090815260409091205460018501554260028501554360038501556004840182905586516128f991601386019190890190612993565b506014830180546001600160a01b038a166401000000000277ffffffffffffffffffffffffffffffffffffffffffffffff1990911660e08a901c171790556015830180546001600160a01b031916331790556040517f03cd1db94c84fbf802bb289f9fec190fc43fcb105eee5554433e8d642ceab11890612981908a908a908a908990612ea7565b60405180910390a15050505050505050565b82805461299f90613273565b90600052602060002090601f0160209004810192826129c15760008555612a07565b82601f106129da57805160ff1916838001178555612a07565b82800160010185558215612a07579182015b82811115612a075782518255916020019190600101906129ec565b50612a13929150612a54565b5090565b6040518061022001604052806011906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b5b80821115612a135760008155600101612a55565b600060208284031215612a7a578081fd5b8135612a85816132f5565b9392505050565b600060208284031215612a9d578081fd5b8151612a85816132f5565b60008060408385031215612aba578081fd5b8235612ac5816132f5565b91506020830135612ad58161330d565b809150509250929050565b600080600060608486031215612af4578081fd5b8335612aff816132f5565b92506020840135612b0f8161330d565b929592945050506040919091013590565b60008060408385031215612b32578182fd5b8235612b3d816132f5565b946020939093013593505050565b600060208284031215612b5c578081fd5b8151612a858161330d565b600060208284031215612b78578081fd5b5035919050565b60008060408385031215612b91578182fd5b50508035926020909101359150565b600060208284031215612bb1578081fd5b815167ffffffffffffffff80821115612bc8578283fd5b818401915084601f830112612bdb578283fd5b815181811115612bed57612bed6132df565b604051601f8201601f19908116603f01168101908382118183101715612c1557612c156132df565b81604052828152876020848701011115612c2d578586fd5b612c3e836020830160208801613230565b979650505050505050565b600060208284031215612c5a578081fd5b5051919050565b60008060408385031215612c73578182fd5b823591506020830135612ad5816132f5565b600080600060608486031215612c99578283fd5b833592506020840135612cab8161330d565b91506040840135612cbb8161330d565b809150509250925092565b600080600080600060a08688031215612cdd578081fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b8060005b6002811015612d315781516001600160a01b0316845260209384019390910190600101612d09565b50505050565b60008151808452612d4f816020860160208601613230565b601f01601f19169290920160200192915050565b60038110612d8157634e487b7160e01b600052602160045260246000fd5b9052565b606085901b6bffffffffffffffffffffffff191681526001600160e01b0319841660148201528251600090612dc1816018850160208801613230565b6018920191820192909252603801949350505050565b6001600160e01b03198316815281546000906004908290600181811c9080831680612e0357607f831692505b6020808410821415612e2257634e487b7160e01b885260228752602488fd5b818015612e365760018114612e4b57612e7b565b60ff1986168a890152848a0188019650612e7b565b60008b815260209020895b86811015612e715781548c82018b0152908501908301612e56565b505087858b010196505b50949a9950505050505050505050565b60008251612e9d818460208701613230565b9190910192915050565b60006001600160a01b038616825263ffffffff60e01b8516602083015260806040830152612ed86080830185612d37565b905082606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612f2157835183529284019291840191600101612f05565b50909695505050505050565b600061032089835260208084018a845b6011811015612f5a57815183529183019190830190600101612f3d565b505050610240840189845b6002811015612f84578151151583529183019190830190600101612f65565b50505050612f96610280840188612d63565b806102a0840152612fa981840187612d37565b915050612fc36102c08301856001600160e01b0319169052565b612fd16102e0830184612d05565b98975050505050505050565b600085825284602083015260806040830152612ffc6080830185612d37565b90506001600160a01b038316606083015295945050505050565b6020808252602e908201527f4e6577206469737075746520726f756e64206d7573742062652073746172746560408201526d642077697468696e20612064617960901b606082015260800190565b82815260408101612a856020830184612d63565b8481526080810161308c6020830186612d63565b6001600160a01b03808516604084015280841660608401525095945050505050565b600082198211156130c1576130c16132c9565b500190565b6000826130e157634e487b7160e01b81526012600452602481fd5b500490565b80825b60018086116130f85750613123565b81870482111561310a5761310a6132c9565b8086161561311757918102915b9490941c9380026130e9565b94509492505050565b6000612a85600019848460008261314557506001612a85565b8161315257506000612a85565b816001811461316857600281146131725761319f565b6001915050612a85565b60ff841115613183576131836132c9565b6001841b915084821115613199576131996132c9565b50612a85565b5060208310610133831016604e8410600b84101617156131d2575081810a838111156131cd576131cd6132c9565b612a85565b6131df84848460016130e6565b8086048211156131f1576131f16132c9565b02949350505050565b6000816000190483118215151615613214576132146132c9565b500290565b60008282101561322b5761322b6132c9565b500390565b60005b8381101561324b578181015183820152602001613233565b83811115612d315750506000910152565b60008161326b5761326b6132c9565b506000190190565b600181811c9082168061328757607f821691505b602082108114156132a857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156132c2576132c26132c9565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461330a57600080fd5b50565b801515811461330a57600080fdfea2646970667358221220536e4cff473bb31c6129dbfb81b7ca596767912786dbac6ba78dda5a551456c364736f6c63430008030033000000000000000000000000bb97c038c338c3dcaf06d5be3b4a3e0b24835f9c0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000007671ea70ce097bc82464b4ab78f79d279356b6cd

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000bb97c038c338c3dcaf06d5be3b4a3e0b24835f9c0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000007671ea70ce097bc82464b4ab78f79d279356b6cd

-----Decoded View---------------
Arg [0] : _tellor (address): 0xbb97c038c338c3dcaf06d5be3b4a3e0b24835f9c
Arg [1] : _disputeFee (uint256): 1000000000000000000
Arg [2] : _teamMultisig (address): 0x7671ea70ce097bc82464b4ab78f79d279356b6cd

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000bb97c038c338c3dcaf06d5be3b4a3e0b24835f9c
Arg [1] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [2] : 0000000000000000000000007671ea70ce097bc82464b4ab78f79d279356b6cd


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.