Source Code
Overview
MATIC Balance
0 MATIC
Token Holdings
More Info
ContractCreator:
Multichain Info
N/A
Loading...
Loading
Contract Name:
Governance
Compiler Version
v0.8.3+commit.8d00100c
Optimization Enabled:
Yes with 300 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.3; import "./TellorFlex.sol"; contract Governance { // Storage TellorFlex public tellor; IERC20 public token; address public teamMultisig; 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 vote 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 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 } // Structs 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 associated with the vote uint256 tallyDate; // timestamp of when the votes were tallied Tally tokenholders; Tally users; Tally reporters; Tally teamMultisig; bool executed; // boolean of is the dispute settled VoteResult result; // VoteResult of did the vote pass? bool isDispute; // boolean of is the vote 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); } _thisVote.fee = _fee; require( token.transferFrom(msg.sender, address(this), _fee), "Fee must be paid" ); // This is the fork 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) ); // Be sure to send enough gas! } 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" ); 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 * reportersVoteSum * multisigVoteSum * usersVoteSum == 0 ) { if (tokenVoteSum == 0) { tokenVoteSum++; } if (reportersVoteSum == 0) { reportersVoteSum++; } if (multisigVoteSum == 0) { multisigVoteSum++; } if (usersVoteSum == 0) { usersVoteSum++; } } 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) public { 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); } }
// 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]; } }
// 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); }
{ "optimizer": { "enabled": true, "runs": 300 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
[{"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"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620033d1380380620033d18339810160408190526200003491620000fc565b600080546001600160a01b0319166001600160a01b03851690811790915560408051637e062a3560e11b8152905163fc0c546a91600480820192602092909190829003018186803b1580156200008957600080fd5b505afa1580156200009e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c4919062000143565b600180546001600160a01b03199081166001600160a01b03938416179091556004939093556002805490931691161790555062000182565b60008060006060848603121562000111578283fd5b83516200011e8162000169565b602085015160408601519194509250620001388162000169565b809150509250925092565b60006020828403121562000155578081fd5b8151620001628162000169565b9392505050565b6001600160a01b03811681146200017f57600080fd5b50565b61323f80620001926000396000f3fe608060405234801561001057600080fd5b50600436106101475760003560e01c8063a3cb1604116100c8578063dbc0c0851161008c578063ec36902511610066578063ec36902514610340578063f98a4eca14610353578063fc0c546a1461036657610147565b8063dbc0c08514610312578063df133bca14610325578063e7b3387c1461033857610147565b8063a3cb16041461029d578063a7c438bc146102b0578063b9ce896b146102ed578063c6384071146102f6578063d3b5e361146102ff57610147565b80634209fff11161010f5780634209fff1146101f25780634ac6eb7c1461022e5780634d318b0e146102415780636169c308146102545780638d8242731461027757610147565b80630e1596ef1461014c5780631959ad5b1461017f5780631f379acc146101aa57806321440a77146101bf578063248638e5146101d2575b600080fd5b61016c61015a366004612a55565b60009081526006602052604090205490565b6040519081526020015b60405180910390f35b600054610192906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6101bd6101b8366004612a6d565b610379565b005b6101bd6101cd366004612a6d565b610b2c565b6101e56101e0366004612a55565b610bb6565b6040516101769190612dd7565b61021e610200366004612957565b6001600160a01b031660009081526007602052604090205460ff1690565b6040519015158152602001610176565b6101bd61023c366004612a0e565b610c18565b6101bd61024f366004612a55565b610c9e565b610267610262366004612a55565b6111fa565b6040516101769493929190612ecb565b61028a610285366004612a55565b6112ce565b6040516101769796959493929190612e1b565b6101bd6102ab366004612996565b6114d0565b61021e6102be366004612b4f565b60008281526008602090815260408083206001600160a01b038516845260160190915290205460ff1692915050565b61016c60045481565b61016c60035481565b6101bd61030d3660046129ce565b611556565b600254610192906001600160a01b031681565b6101bd610333366004612b73565b6115dd565b60035461016c565b6101bd61034e366004612a6d565b611c0c565b6101bd610361366004612a55565b611c81565b600154610192906001600160a01b031681565b600054604051630935408d60e41b815260048101849052602481018390526001600160a01b039091169063935408d09060440160206040518083038186803b1580156103c457600080fd5b505afa1580156103d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fc9190612b37565b6104585760405162461bcd60e51b815260206004820152602260248201527f6e6f2076616c75652065786973747320617420676976656e2074696d6573746160448201526106d760f41b60648201526084015b60405180910390fd5b60408051602080820185905281830184905282518083038401815260609092019092528051910120600380549060006104908361319c565b90915550506003546000828152600960209081526040822080546001818101835582855292842001849055918490529054111561055757600082815260096020526040812080546104e390600290613107565b8154811061050157634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426105349190613107565b106105515760405162461bcd60e51b815260040161044f90612f04565b5061066d565b60008054906101000a90046001600160a01b03166001600160a01b0316633321fc416040518163ffffffff1660e01b815260040160206040518083038186803b1580156105a357600080fd5b505afa1580156105b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105db9190612b37565b6105e58442613107565b1061064d5760405162461bcd60e51b815260206004820152603260248201527f44697370757465206d75737420626520737461727465642077697468696e207260448201527165706f7274696e67206c6f636b2074696d6560701b606482015260840161044f565b60008481526006602052604081208054916106678361319c565b91905055505b60008181526008602090815260408083206005909252808320878155600181018790559254905163c5958af960e01b815260048101889052602481018790529192916001600160a01b039091169063c5958af99060440160006040518083038186803b1580156106dc57600080fd5b505afa1580156106f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107189190810190612a8e565b805161072e916002840191602090910190612881565b5060005460405163703e2a4360e11b815260048101889052602481018790526001600160a01b039091169063e07c54869060440160206040518083038186803b15801561077a57600080fd5b505afa15801561078e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b2919061297a565b600380830180546001600160a01b03939093166001600160a01b0319938416179055858455601584018054909216331790915543908301554260028301556000848152600960205260408120805460018581019190915560128501805462ff00001916620100001790559054141561085e5760008781526006602052604090205461083f90600190613107565b61084a90600261301a565b60045461085791906130e8565b9050610894565b60008581526009602052604090205461087990600190613107565b61088490600261301a565b60045461089191906130e8565b90505b60048381018290556001546040516323b872dd60e01b81523392810192909252306024830152604482018390526001600160a01b0316906323b872dd90606401602060405180830381600087803b1580156108ee57600080fd5b505af1158015610902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109269190612a39565b6109655760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b60008581526009602052604090205460011415610a7557600054600383015460405163137f0a8d60e21b81526001600160a01b039182166004820152306024820152911690634dfc2a3490604401602060405180830381600087803b1580156109cd57600080fd5b505af11580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a059190612b37565b6004838101919091556000546040516316d7b73f60e21b8152918201899052602482018890526001600160a01b031690635b5edcfc90604401600060405180830381600087803b158015610a5857600080fd5b505af1158015610a6c573d6000803e3d6000fd5b50505050610acc565b6000858152600960205260408120805460059291908290610aa657634e487b7160e01b600052603260045260246000fd5b906000526020600020015481526020019081526020016000206004015482600401819055505b600382015460408051868152602081018a90529081018890526001600160a01b0390911660608201527f12b7317353cd7caa8eae8057464e3de356c1429d814fb3421797eccb19043044906080015b60405180910390a150505050505050565b600054604080518082018252601a81527f6368616e67655374616b65416d6f756e742875696e74323536290000000000006020918201528151908101859052610bb2926001600160a01b0316917fca79b5a978ea700f37e874524ca56caf88471abdb2cff892cab3e91ff005e0a191015b6040516020818303038152906040528461258a565b5050565b600081815260096020908152604091829020805483518184028101840190945280845260609392830182828015610c0c57602002820191906000526020600020905b815481526020019060010190808311610bf8575b50505050509050919050565b60005460408051808201825260208082527f6368616e6765476f7665726e616e636541646472657373286164647265737329918101919091529051610bb2926001600160a01b0316917f0636769e56486090c573831c9de80fac4458ca89aa37a2afff688bfcbc1ad71191610b9d918791016001600160a01b0391909116815260200190565b6000818152600860205260409020601281015460ff1615610d0b5760405162461bcd60e51b815260206004820152602160248201527f446973707574652068617320616c7265616479206265656e20657865637574656044820152601960fa1b606482015260840161044f565b600581015415610d5d5760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b600354821115610da55760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60128101546202a3009062010000900460ff16610dc2575062093a805b80826002015442610dd39190613107565b11610e205760405162461bcd60e51b815260206004820152601f60248201527f54696d6520666f7220766f74696e6720686173206e6f7420656c617073656400604482015260640161044f565b60088201546007830154600684015460009291610e3c91612f9c565b610e469190612f9c565b600e840154600d850154600c860154929350600092610e659190612f9c565b610e6f9190612f9c565b60118501546010860154600f870154929350600092610e8e9190612f9c565b610e989190612f9c565b600b860154600a8701546009880154929350600092610eb79190612f9c565b610ec19190612f9c565b90508082610ecf85876130e8565b610ed991906130e8565b610ee391906130e8565b610f335783610efa5783610ef68161319c565b9450505b82610f0d5782610f098161319c565b9350505b81610f205781610f1c8161319c565b9250505b80610f335780610f2f8161319c565b9150505b60098601546000908390610f49906127106130e8565b610f539190612fb4565b600f8801548490610f66906127106130e8565b610f709190612fb4565b600c8901548690610f83906127106130e8565b610f8d9190612fb4565b60068a01548890610fa0906127106130e8565b610faa9190612fb4565b610fb49190612f9c565b610fbe9190612f9c565b610fc89190612f9c565b90506000838860090160010154612710610fe291906130e8565b610fec9190612fb4565b60108901548590610fff906127106130e8565b6110099190612fb4565b600d8a0154879061101c906127106130e8565b6110269190612fb4565b60078b01548990611039906127106130e8565b6110439190612fb4565b61104d9190612f9c565b6110579190612f9c565b6110619190612f9c565b9050600084896009016002015461271061107b91906130e8565b6110859190612fb4565b60118a01548690611098906127106130e8565b6110a29190612fb4565b600e8b015488906110b5906127106130e8565b6110bf9190612fb4565b60088c01548a906110d2906127106130e8565b6110dc9190612fb4565b6110e69190612f9c565b6110f09190612f9c565b6110fa9190612f9c565b905082811015801561110c5750818110155b80156111225750601289015462010000900460ff165b15611145576012890180546002919061ff001916610100835b0217905550611173565b81831115611165576012890180546001919061ff0019166101008361113b565b60128901805461ff00191690555b4260058a81019190915560128a015460158b015460008d81526020939093526040928390206003015492517fa2d4e500801849d40ad00f0f12ba92a5263f83ec68946e647be95cfbe581c7b6936111e6938f9361010090910460ff16926001600160a01b03918216929190911690612f66565b60405180910390a150505050505050505050565b6000818152600560205260408120805460018201546003830154600284018054869560609587959194909391926001600160a01b0390911690829061123e90613161565b80601f016020809104026020016040519081016040528092919081815260200182805461126a90613161565b80156112b75780601f1061128c576101008083540402835291602001916112b7565b820191906000526020600020905b81548152906001019060200180831161129a57829003601f168201915b505050505091509450945094509450509193509193565b60006112d8612905565b6112e0612924565b6000606060006112ee612924565b6000888152600860208181526040928390208054845161022081018652600183015481526002830154818501526003830154818701526004830154606082015260058301546080820152600683015460a0820152600783015460c08201529382015460e080860191909152600983015461010080870191909152600a840154610120870152600b840154610140870152600c840154610160870152600d840154610180870152600e8401546101a0870152600f8401546101c087015260108401546101e0870152601184015461020087015286518088018852601285015460ff80821615158352620100008204811615158389015260148701548a51808c01909b526001600160a01b03640100000000820481168c52601589015416988b0198909852601387018054979a969998939794909204169490939190911b91839061143690613161565b80601f016020809104026020016040519081016040528092919081815260200182805461146290613161565b80156114af5780601f10611484576101008083540402835291602001916114af565b820191906000526020600020905b81548152906001019060200180831161149257829003601f168201915b50505050509250975097509750975097509750975050919395979092949650565b33301461152b5760405162461bcd60e51b8152602060048201526024808201527f4f6e6c7920676f7665726e616e63652063616e207570646174652075736572206044820152631b1a5cdd60e21b606482015260840161044f565b6001600160a01b03919091166000908152600760205260409020805460ff1916911515919091179055565b604080518082018252601c81527f757064617465557365724c69737428616464726573732c626f6f6c290000000060209182015290516115d89130917fa3cb1604d428d5b2db415cab07e750952a0559e3ea14fc2ad01393fcccac6aee91610b9d9188918891016001600160a01b039290921682521515602082015260400190565b505050565b6003548311156116255760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60008381526008602052604090206005810154156116855760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b33600090815260168201602052604090205460ff16156116e75760405162461bcd60e51b815260206004820152601860248201527f53656e6465722068617320616c726561647920766f7465640000000000000000604482015260640161044f565b336000818152601683016020526040808220805460ff191660019081179091555490516370a0823160e01b8152600481019390935290916001600160a01b03909116906370a082319060240160206040518083038186803b15801561174b57600080fd5b505afa15801561175f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117839190612b37565b60008054604051630733bdef60e41b8152336004820152929350909182916001600160a01b03169063733bdef09060240160a06040518083038186803b1580156117cc57600080fd5b505afa1580156117e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118049190612bb4565b5050925092505080826118179190612f9c565b6118219084612f9c565b601285015490935062010000900460ff16801561183b5750845b1561196f578215611863578284600601600201600082825461185d9190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b1580156118a657600080fd5b505afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612b37565b92508215611903578284600c0160020160008282546118fd9190612f9c565b90915550505b3360009081526007602052604090205460ff16156119395760018460090160020160008282546119339190612f9c565b90915550505b6002546001600160a01b031633141561196a57600184600f0160020160008282546119649190612f9c565b90915550505b611bc3565b8515611a9957821561199857828460060160000160008282546119929190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b1580156119db57600080fd5b505afa1580156119ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a139190612b37565b92508215611a38578284600c016000016000828254611a329190612f9c565b90915550505b3360009081526007602052604090205460ff1615611a6e576001846009016000016000828254611a689190612f9c565b90915550505b6002546001600160a01b031633141561196a57600184600f0160000160008282546119649190612f9c565b8215611abc5782846006016001016000828254611ab69190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b158015611aff57600080fd5b505afa158015611b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b379190612b37565b92508215611b5c578284600c016001016000828254611b569190612f9c565b90915550505b3360009081526007602052604090205460ff1615611b92576001846009016001016000828254611b8c9190612f9c565b90915550505b6002546001600160a01b0316331415611bc357600184600f016001016000828254611bbd9190612f9c565b90915550505b604080518881528715156020820152339181019190915285151560608201527fbe6f1c58cc15c8e86d6f0ef23c5a30eb33319af3b57f6b7d9b56ccfa87696b8490608001610b1b565b600054604080518082018252601c81527f6368616e67655265706f7274696e674c6f636b2875696e7432353629000000006020918201528151908101859052610bb2926001600160a01b0316917f5d183cfa1084f72f49f0f81fe5d34bf9533a659ae85960ce554cbcf02302ca309101610b9d565b6000818152600860205260409020600354821115611ce15760405162461bcd60e51b815260206004820152601560248201527f566f7465204944206d7573742062652076616c69640000000000000000000000604482015260640161044f565b601281015460ff1615611d365760405162461bcd60e51b815260206004820152601660248201527f566f746520686173206265656e20657865637574656400000000000000000000604482015260640161044f565b6000816005015411611d8a5760405162461bcd60e51b815260206004820152601460248201527f566f7465206d7573742062652074616c6c696564000000000000000000000000604482015260640161044f565b6001810154815460009081526009602052604090205414611ded5760405162461bcd60e51b815260206004820152601660248201527f4d757374206265207468652066696e616c20766f746500000000000000000000604482015260640161044f565b6001810154611dff90620151806130e8565b6005820154611e0e9042613107565b1015611e705760405162461bcd60e51b815260206004820152602b60248201527f566f7465206e6565647320746f2062652074616c6c69656420616e642074696d60448201526a65206d757374207061737360a81b606482015260840161044f565b60128101805460ff19166001179081905562010000900460ff16611fa75760016012820154610100900460ff166002811115611ebc57634e487b7160e01b600052602160045260246000fd5b1415611f5c5760148101546040516001600160a01b03640100000000830416916000916060918491611ef99160e01b906013880190602001612cc5565b60408051601f1981840301815290829052611f1391612d79565b6000604051808303816000865af19150503d8060008114611f50576040519150601f19603f3d011682016040523d82523d6000602084013e611f55565b606091505b5050505050505b60128101546040517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da491611f9a918591610100900460ff1690612f52565b60405180910390a1610bb2565b600082815260056020908152604080832060018501548554855260099093529220541415611ff15780546000908152600660205260408120805491611feb8361314a565b91905055505b60008060016012850154610100900460ff16600281111561202257634e487b7160e01b600052602160045260246000fd5b14156121e057835460009081526009602052604090205491505b81156121db578354600090815260096020526040902061205d600184613107565b8154811061207b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050600860008281526020019081526020016000209350816001141561213857600154601585015460048581015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b1580156120fe57600080fd5b505af1158015612112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121369190612a39565b505b600154601585015460048087015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561219057600080fd5b505af11580156121a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c89190612a39565b50816121d38161314a565b92505061203c565b61252f565b60026012850154610100900460ff16600281111561220e57634e487b7160e01b600052602160045260246000fd5b14156123c457835460009081526009602052604090205491505b811561232e5783546000908152600960205260409020612249600184613107565b8154811061226757634e487b7160e01b600052603260045260246000fd5b60009182526020808320919091015480835260089091526040918290206001546015820154600480840154955163a9059cbb60e01b81526001600160a01b03928316918101919091526024810195909552919750919350169063a9059cbb90604401602060405180830381600087803b1580156122e357600080fd5b505af11580156122f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231b9190612a39565b50816123268161314a565b925050612228565b600154600384015460048086015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561238657600080fd5b505af115801561239a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123be9190612a39565b5061252f565b60006012850154610100900460ff1660028111156123f257634e487b7160e01b600052602160045260246000fd5b141561252f57835460009081526009602052604081205492505b8215612491578454600090815260096020526040902061242d600185613107565b8154811061244b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154915060086000838152602001908152602001600020945084600401548161247d9190612f9c565b9050826124898161314a565b93505061240c565b60048401546124a09082612f9c565b600154600386015460405163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350169063a9059cbb90604401602060405180830381600087803b1580156124f457600080fd5b505af1158015612508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252c9190612a39565b50505b600085815260086020526040908190206012015490517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da49161257b918891610100900460ff1690612f52565b60405180910390a15050505050565b6003805490600061259a8361319c565b90915550506003546000818152600860205260409020826125b9574292505b6000868686866040516020016125d29493929190612c73565b60408051601f1981840301815291815281516020928301206000818152600984529182208054600181810183558285529484200187905591819052905490925011156126a4576000818152600960205260408120805461263490600290613107565b8154811061265257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426126859190613107565b106126a25760405162461bcd60e51b815260040161044f90612f04565b505b6000818152600960205260408120546126bf90600190613107565b6126ca90600261301a565b6126dc90678ac7230489e800006130e8565b6001546040516323b872dd60e01b8152336004820152306024820152604481018390529192506001600160a01b0316906323b872dd90606401602060405180830381600087803b15801561272f57600080fd5b505af1158015612743573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127679190612a39565b6127a65760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b81835560008281526009602090815260409091205460018501554260028501554360038501556004840182905586516127e791601386019190890190612881565b506014830180546001600160a01b038a166401000000000277ffffffffffffffffffffffffffffffffffffffffffffffff1990911660e08a901c171790556015830180546001600160a01b031916331790556040517f03cd1db94c84fbf802bb289f9fec190fc43fcb105eee5554433e8d642ceab1189061286f908a908a908a908990612d95565b60405180910390a15050505050505050565b82805461288d90613161565b90600052602060002090601f0160209004810192826128af57600085556128f5565b82601f106128c857805160ff19168380011785556128f5565b828001600101855582156128f5579182015b828111156128f55782518255916020019190600101906128da565b50612901929150612942565b5090565b6040518061022001604052806011906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b5b808211156129015760008155600101612943565b600060208284031215612968578081fd5b8135612973816131e3565b9392505050565b60006020828403121561298b578081fd5b8151612973816131e3565b600080604083850312156129a8578081fd5b82356129b3816131e3565b915060208301356129c3816131fb565b809150509250929050565b6000806000606084860312156129e2578081fd5b83356129ed816131e3565b925060208401356129fd816131fb565b929592945050506040919091013590565b60008060408385031215612a20578182fd5b8235612a2b816131e3565b946020939093013593505050565b600060208284031215612a4a578081fd5b8151612973816131fb565b600060208284031215612a66578081fd5b5035919050565b60008060408385031215612a7f578182fd5b50508035926020909101359150565b600060208284031215612a9f578081fd5b815167ffffffffffffffff80821115612ab6578283fd5b818401915084601f830112612ac9578283fd5b815181811115612adb57612adb6131cd565b604051601f8201601f19908116603f01168101908382118183101715612b0357612b036131cd565b81604052828152876020848701011115612b1b578586fd5b612b2c83602083016020880161311e565b979650505050505050565b600060208284031215612b48578081fd5b5051919050565b60008060408385031215612b61578182fd5b8235915060208301356129c3816131e3565b600080600060608486031215612b87578283fd5b833592506020840135612b99816131fb565b91506040840135612ba9816131fb565b809150509250925092565b600080600080600060a08688031215612bcb578081fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b8060005b6002811015612c1f5781516001600160a01b0316845260209384019390910190600101612bf7565b50505050565b60008151808452612c3d81602086016020860161311e565b601f01601f19169290920160200192915050565b60038110612c6f57634e487b7160e01b600052602160045260246000fd5b9052565b606085901b6bffffffffffffffffffffffff191681526001600160e01b0319841660148201528251600090612caf81601885016020880161311e565b6018920191820192909252603801949350505050565b6001600160e01b03198316815281546000906004908290600181811c9080831680612cf157607f831692505b6020808410821415612d1057634e487b7160e01b885260228752602488fd5b818015612d245760018114612d3957612d69565b60ff1986168a890152848a0188019650612d69565b60008b815260209020895b86811015612d5f5781548c82018b0152908501908301612d44565b505087858b010196505b50949a9950505050505050505050565b60008251612d8b81846020870161311e565b9190910192915050565b60006001600160a01b038616825263ffffffff60e01b8516602083015260806040830152612dc66080830185612c25565b905082606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e0f57835183529284019291840191600101612df3565b50909695505050505050565b600061032089835260208084018a845b6011811015612e4857815183529183019190830190600101612e2b565b505050610240840189845b6002811015612e72578151151583529183019190830190600101612e53565b50505050612e84610280840188612c51565b806102a0840152612e9781840187612c25565b915050612eb16102c08301856001600160e01b0319169052565b612ebf6102e0830184612bf3565b98975050505050505050565b600085825284602083015260806040830152612eea6080830185612c25565b90506001600160a01b038316606083015295945050505050565b6020808252602e908201527f4e6577206469737075746520726f756e64206d7573742062652073746172746560408201526d642077697468696e20612064617960901b606082015260800190565b828152604081016129736020830184612c51565b84815260808101612f7a6020830186612c51565b6001600160a01b03808516604084015280841660608401525095945050505050565b60008219821115612faf57612faf6131b7565b500190565b600082612fcf57634e487b7160e01b81526012600452602481fd5b500490565b80825b6001808611612fe65750613011565b818704821115612ff857612ff86131b7565b8086161561300557918102915b9490941c938002612fd7565b94509492505050565b6000612973600019848460008261303357506001612973565b8161304057506000612973565b816001811461305657600281146130605761308d565b6001915050612973565b60ff841115613071576130716131b7565b6001841b915084821115613087576130876131b7565b50612973565b5060208310610133831016604e8410600b84101617156130c0575081810a838111156130bb576130bb6131b7565b612973565b6130cd8484846001612fd4565b8086048211156130df576130df6131b7565b02949350505050565b6000816000190483118215151615613102576131026131b7565b500290565b600082821015613119576131196131b7565b500390565b60005b83811015613139578181015183820152602001613121565b83811115612c1f5750506000910152565b600081613159576131596131b7565b506000190190565b600181811c9082168061317557607f821691505b6020821081141561319657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156131b0576131b06131b7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146131f857600080fd5b50565b80151581146131f857600080fdfea26469706673582212200e66ea4a5edfc6ebd8a2364676a30b97a0e04b0be80b6d19a89932b9eba6e74364736f6c6343000803003300000000000000000000000041b66dd93b03e89d29114a7613a6f9f0d4f401780000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000080fc34a2f9ffe86f41580f47368289c402dec660
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101475760003560e01c8063a3cb1604116100c8578063dbc0c0851161008c578063ec36902511610066578063ec36902514610340578063f98a4eca14610353578063fc0c546a1461036657610147565b8063dbc0c08514610312578063df133bca14610325578063e7b3387c1461033857610147565b8063a3cb16041461029d578063a7c438bc146102b0578063b9ce896b146102ed578063c6384071146102f6578063d3b5e361146102ff57610147565b80634209fff11161010f5780634209fff1146101f25780634ac6eb7c1461022e5780634d318b0e146102415780636169c308146102545780638d8242731461027757610147565b80630e1596ef1461014c5780631959ad5b1461017f5780631f379acc146101aa57806321440a77146101bf578063248638e5146101d2575b600080fd5b61016c61015a366004612a55565b60009081526006602052604090205490565b6040519081526020015b60405180910390f35b600054610192906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6101bd6101b8366004612a6d565b610379565b005b6101bd6101cd366004612a6d565b610b2c565b6101e56101e0366004612a55565b610bb6565b6040516101769190612dd7565b61021e610200366004612957565b6001600160a01b031660009081526007602052604090205460ff1690565b6040519015158152602001610176565b6101bd61023c366004612a0e565b610c18565b6101bd61024f366004612a55565b610c9e565b610267610262366004612a55565b6111fa565b6040516101769493929190612ecb565b61028a610285366004612a55565b6112ce565b6040516101769796959493929190612e1b565b6101bd6102ab366004612996565b6114d0565b61021e6102be366004612b4f565b60008281526008602090815260408083206001600160a01b038516845260160190915290205460ff1692915050565b61016c60045481565b61016c60035481565b6101bd61030d3660046129ce565b611556565b600254610192906001600160a01b031681565b6101bd610333366004612b73565b6115dd565b60035461016c565b6101bd61034e366004612a6d565b611c0c565b6101bd610361366004612a55565b611c81565b600154610192906001600160a01b031681565b600054604051630935408d60e41b815260048101849052602481018390526001600160a01b039091169063935408d09060440160206040518083038186803b1580156103c457600080fd5b505afa1580156103d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fc9190612b37565b6104585760405162461bcd60e51b815260206004820152602260248201527f6e6f2076616c75652065786973747320617420676976656e2074696d6573746160448201526106d760f41b60648201526084015b60405180910390fd5b60408051602080820185905281830184905282518083038401815260609092019092528051910120600380549060006104908361319c565b90915550506003546000828152600960209081526040822080546001818101835582855292842001849055918490529054111561055757600082815260096020526040812080546104e390600290613107565b8154811061050157634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426105349190613107565b106105515760405162461bcd60e51b815260040161044f90612f04565b5061066d565b60008054906101000a90046001600160a01b03166001600160a01b0316633321fc416040518163ffffffff1660e01b815260040160206040518083038186803b1580156105a357600080fd5b505afa1580156105b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105db9190612b37565b6105e58442613107565b1061064d5760405162461bcd60e51b815260206004820152603260248201527f44697370757465206d75737420626520737461727465642077697468696e207260448201527165706f7274696e67206c6f636b2074696d6560701b606482015260840161044f565b60008481526006602052604081208054916106678361319c565b91905055505b60008181526008602090815260408083206005909252808320878155600181018790559254905163c5958af960e01b815260048101889052602481018790529192916001600160a01b039091169063c5958af99060440160006040518083038186803b1580156106dc57600080fd5b505afa1580156106f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107189190810190612a8e565b805161072e916002840191602090910190612881565b5060005460405163703e2a4360e11b815260048101889052602481018790526001600160a01b039091169063e07c54869060440160206040518083038186803b15801561077a57600080fd5b505afa15801561078e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b2919061297a565b600380830180546001600160a01b03939093166001600160a01b0319938416179055858455601584018054909216331790915543908301554260028301556000848152600960205260408120805460018581019190915560128501805462ff00001916620100001790559054141561085e5760008781526006602052604090205461083f90600190613107565b61084a90600261301a565b60045461085791906130e8565b9050610894565b60008581526009602052604090205461087990600190613107565b61088490600261301a565b60045461089191906130e8565b90505b60048381018290556001546040516323b872dd60e01b81523392810192909252306024830152604482018390526001600160a01b0316906323b872dd90606401602060405180830381600087803b1580156108ee57600080fd5b505af1158015610902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109269190612a39565b6109655760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b60008581526009602052604090205460011415610a7557600054600383015460405163137f0a8d60e21b81526001600160a01b039182166004820152306024820152911690634dfc2a3490604401602060405180830381600087803b1580156109cd57600080fd5b505af11580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a059190612b37565b6004838101919091556000546040516316d7b73f60e21b8152918201899052602482018890526001600160a01b031690635b5edcfc90604401600060405180830381600087803b158015610a5857600080fd5b505af1158015610a6c573d6000803e3d6000fd5b50505050610acc565b6000858152600960205260408120805460059291908290610aa657634e487b7160e01b600052603260045260246000fd5b906000526020600020015481526020019081526020016000206004015482600401819055505b600382015460408051868152602081018a90529081018890526001600160a01b0390911660608201527f12b7317353cd7caa8eae8057464e3de356c1429d814fb3421797eccb19043044906080015b60405180910390a150505050505050565b600054604080518082018252601a81527f6368616e67655374616b65416d6f756e742875696e74323536290000000000006020918201528151908101859052610bb2926001600160a01b0316917fca79b5a978ea700f37e874524ca56caf88471abdb2cff892cab3e91ff005e0a191015b6040516020818303038152906040528461258a565b5050565b600081815260096020908152604091829020805483518184028101840190945280845260609392830182828015610c0c57602002820191906000526020600020905b815481526020019060010190808311610bf8575b50505050509050919050565b60005460408051808201825260208082527f6368616e6765476f7665726e616e636541646472657373286164647265737329918101919091529051610bb2926001600160a01b0316917f0636769e56486090c573831c9de80fac4458ca89aa37a2afff688bfcbc1ad71191610b9d918791016001600160a01b0391909116815260200190565b6000818152600860205260409020601281015460ff1615610d0b5760405162461bcd60e51b815260206004820152602160248201527f446973707574652068617320616c7265616479206265656e20657865637574656044820152601960fa1b606482015260840161044f565b600581015415610d5d5760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b600354821115610da55760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60128101546202a3009062010000900460ff16610dc2575062093a805b80826002015442610dd39190613107565b11610e205760405162461bcd60e51b815260206004820152601f60248201527f54696d6520666f7220766f74696e6720686173206e6f7420656c617073656400604482015260640161044f565b60088201546007830154600684015460009291610e3c91612f9c565b610e469190612f9c565b600e840154600d850154600c860154929350600092610e659190612f9c565b610e6f9190612f9c565b60118501546010860154600f870154929350600092610e8e9190612f9c565b610e989190612f9c565b600b860154600a8701546009880154929350600092610eb79190612f9c565b610ec19190612f9c565b90508082610ecf85876130e8565b610ed991906130e8565b610ee391906130e8565b610f335783610efa5783610ef68161319c565b9450505b82610f0d5782610f098161319c565b9350505b81610f205781610f1c8161319c565b9250505b80610f335780610f2f8161319c565b9150505b60098601546000908390610f49906127106130e8565b610f539190612fb4565b600f8801548490610f66906127106130e8565b610f709190612fb4565b600c8901548690610f83906127106130e8565b610f8d9190612fb4565b60068a01548890610fa0906127106130e8565b610faa9190612fb4565b610fb49190612f9c565b610fbe9190612f9c565b610fc89190612f9c565b90506000838860090160010154612710610fe291906130e8565b610fec9190612fb4565b60108901548590610fff906127106130e8565b6110099190612fb4565b600d8a0154879061101c906127106130e8565b6110269190612fb4565b60078b01548990611039906127106130e8565b6110439190612fb4565b61104d9190612f9c565b6110579190612f9c565b6110619190612f9c565b9050600084896009016002015461271061107b91906130e8565b6110859190612fb4565b60118a01548690611098906127106130e8565b6110a29190612fb4565b600e8b015488906110b5906127106130e8565b6110bf9190612fb4565b60088c01548a906110d2906127106130e8565b6110dc9190612fb4565b6110e69190612f9c565b6110f09190612f9c565b6110fa9190612f9c565b905082811015801561110c5750818110155b80156111225750601289015462010000900460ff165b15611145576012890180546002919061ff001916610100835b0217905550611173565b81831115611165576012890180546001919061ff0019166101008361113b565b60128901805461ff00191690555b4260058a81019190915560128a015460158b015460008d81526020939093526040928390206003015492517fa2d4e500801849d40ad00f0f12ba92a5263f83ec68946e647be95cfbe581c7b6936111e6938f9361010090910460ff16926001600160a01b03918216929190911690612f66565b60405180910390a150505050505050505050565b6000818152600560205260408120805460018201546003830154600284018054869560609587959194909391926001600160a01b0390911690829061123e90613161565b80601f016020809104026020016040519081016040528092919081815260200182805461126a90613161565b80156112b75780601f1061128c576101008083540402835291602001916112b7565b820191906000526020600020905b81548152906001019060200180831161129a57829003601f168201915b505050505091509450945094509450509193509193565b60006112d8612905565b6112e0612924565b6000606060006112ee612924565b6000888152600860208181526040928390208054845161022081018652600183015481526002830154818501526003830154818701526004830154606082015260058301546080820152600683015460a0820152600783015460c08201529382015460e080860191909152600983015461010080870191909152600a840154610120870152600b840154610140870152600c840154610160870152600d840154610180870152600e8401546101a0870152600f8401546101c087015260108401546101e0870152601184015461020087015286518088018852601285015460ff80821615158352620100008204811615158389015260148701548a51808c01909b526001600160a01b03640100000000820481168c52601589015416988b0198909852601387018054979a969998939794909204169490939190911b91839061143690613161565b80601f016020809104026020016040519081016040528092919081815260200182805461146290613161565b80156114af5780601f10611484576101008083540402835291602001916114af565b820191906000526020600020905b81548152906001019060200180831161149257829003601f168201915b50505050509250975097509750975097509750975050919395979092949650565b33301461152b5760405162461bcd60e51b8152602060048201526024808201527f4f6e6c7920676f7665726e616e63652063616e207570646174652075736572206044820152631b1a5cdd60e21b606482015260840161044f565b6001600160a01b03919091166000908152600760205260409020805460ff1916911515919091179055565b604080518082018252601c81527f757064617465557365724c69737428616464726573732c626f6f6c290000000060209182015290516115d89130917fa3cb1604d428d5b2db415cab07e750952a0559e3ea14fc2ad01393fcccac6aee91610b9d9188918891016001600160a01b039290921682521515602082015260400190565b505050565b6003548311156116255760405162461bcd60e51b8152602060048201526013602482015272159bdd1948191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161044f565b60008381526008602052604090206005810154156116855760405162461bcd60e51b815260206004820152601d60248201527f566f74652068617320616c7265616479206265656e2074616c6c696564000000604482015260640161044f565b33600090815260168201602052604090205460ff16156116e75760405162461bcd60e51b815260206004820152601860248201527f53656e6465722068617320616c726561647920766f7465640000000000000000604482015260640161044f565b336000818152601683016020526040808220805460ff191660019081179091555490516370a0823160e01b8152600481019390935290916001600160a01b03909116906370a082319060240160206040518083038186803b15801561174b57600080fd5b505afa15801561175f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117839190612b37565b60008054604051630733bdef60e41b8152336004820152929350909182916001600160a01b03169063733bdef09060240160a06040518083038186803b1580156117cc57600080fd5b505afa1580156117e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118049190612bb4565b5050925092505080826118179190612f9c565b6118219084612f9c565b601285015490935062010000900460ff16801561183b5750845b1561196f578215611863578284600601600201600082825461185d9190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b1580156118a657600080fd5b505afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612b37565b92508215611903578284600c0160020160008282546118fd9190612f9c565b90915550505b3360009081526007602052604090205460ff16156119395760018460090160020160008282546119339190612f9c565b90915550505b6002546001600160a01b031633141561196a57600184600f0160020160008282546119649190612f9c565b90915550505b611bc3565b8515611a9957821561199857828460060160000160008282546119929190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b1580156119db57600080fd5b505afa1580156119ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a139190612b37565b92508215611a38578284600c016000016000828254611a329190612f9c565b90915550505b3360009081526007602052604090205460ff1615611a6e576001846009016000016000828254611a689190612f9c565b90915550505b6002546001600160a01b031633141561196a57600184600f0160000160008282546119649190612f9c565b8215611abc5782846006016001016000828254611ab69190612f9c565b90915550505b600054604051631c3c149f60e11b81523360048201526001600160a01b0390911690633878293e9060240160206040518083038186803b158015611aff57600080fd5b505afa158015611b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b379190612b37565b92508215611b5c578284600c016001016000828254611b569190612f9c565b90915550505b3360009081526007602052604090205460ff1615611b92576001846009016001016000828254611b8c9190612f9c565b90915550505b6002546001600160a01b0316331415611bc357600184600f016001016000828254611bbd9190612f9c565b90915550505b604080518881528715156020820152339181019190915285151560608201527fbe6f1c58cc15c8e86d6f0ef23c5a30eb33319af3b57f6b7d9b56ccfa87696b8490608001610b1b565b600054604080518082018252601c81527f6368616e67655265706f7274696e674c6f636b2875696e7432353629000000006020918201528151908101859052610bb2926001600160a01b0316917f5d183cfa1084f72f49f0f81fe5d34bf9533a659ae85960ce554cbcf02302ca309101610b9d565b6000818152600860205260409020600354821115611ce15760405162461bcd60e51b815260206004820152601560248201527f566f7465204944206d7573742062652076616c69640000000000000000000000604482015260640161044f565b601281015460ff1615611d365760405162461bcd60e51b815260206004820152601660248201527f566f746520686173206265656e20657865637574656400000000000000000000604482015260640161044f565b6000816005015411611d8a5760405162461bcd60e51b815260206004820152601460248201527f566f7465206d7573742062652074616c6c696564000000000000000000000000604482015260640161044f565b6001810154815460009081526009602052604090205414611ded5760405162461bcd60e51b815260206004820152601660248201527f4d757374206265207468652066696e616c20766f746500000000000000000000604482015260640161044f565b6001810154611dff90620151806130e8565b6005820154611e0e9042613107565b1015611e705760405162461bcd60e51b815260206004820152602b60248201527f566f7465206e6565647320746f2062652074616c6c69656420616e642074696d60448201526a65206d757374207061737360a81b606482015260840161044f565b60128101805460ff19166001179081905562010000900460ff16611fa75760016012820154610100900460ff166002811115611ebc57634e487b7160e01b600052602160045260246000fd5b1415611f5c5760148101546040516001600160a01b03640100000000830416916000916060918491611ef99160e01b906013880190602001612cc5565b60408051601f1981840301815290829052611f1391612d79565b6000604051808303816000865af19150503d8060008114611f50576040519150601f19603f3d011682016040523d82523d6000602084013e611f55565b606091505b5050505050505b60128101546040517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da491611f9a918591610100900460ff1690612f52565b60405180910390a1610bb2565b600082815260056020908152604080832060018501548554855260099093529220541415611ff15780546000908152600660205260408120805491611feb8361314a565b91905055505b60008060016012850154610100900460ff16600281111561202257634e487b7160e01b600052602160045260246000fd5b14156121e057835460009081526009602052604090205491505b81156121db578354600090815260096020526040902061205d600184613107565b8154811061207b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050600860008281526020019081526020016000209350816001141561213857600154601585015460048581015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b1580156120fe57600080fd5b505af1158015612112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121369190612a39565b505b600154601585015460048087015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561219057600080fd5b505af11580156121a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c89190612a39565b50816121d38161314a565b92505061203c565b61252f565b60026012850154610100900460ff16600281111561220e57634e487b7160e01b600052602160045260246000fd5b14156123c457835460009081526009602052604090205491505b811561232e5783546000908152600960205260409020612249600184613107565b8154811061226757634e487b7160e01b600052603260045260246000fd5b60009182526020808320919091015480835260089091526040918290206001546015820154600480840154955163a9059cbb60e01b81526001600160a01b03928316918101919091526024810195909552919750919350169063a9059cbb90604401602060405180830381600087803b1580156122e357600080fd5b505af11580156122f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231b9190612a39565b50816123268161314a565b925050612228565b600154600384015460048086015460405163a9059cbb60e01b81526001600160a01b0393841692810192909252602482015291169063a9059cbb90604401602060405180830381600087803b15801561238657600080fd5b505af115801561239a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123be9190612a39565b5061252f565b60006012850154610100900460ff1660028111156123f257634e487b7160e01b600052602160045260246000fd5b141561252f57835460009081526009602052604081205492505b8215612491578454600090815260096020526040902061242d600185613107565b8154811061244b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154915060086000838152602001908152602001600020945084600401548161247d9190612f9c565b9050826124898161314a565b93505061240c565b60048401546124a09082612f9c565b600154600386015460405163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350169063a9059cbb90604401602060405180830381600087803b1580156124f457600080fd5b505af1158015612508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252c9190612a39565b50505b600085815260086020526040908190206012015490517f40d231bf91823121de9e1c012d95f835ea5684dc1d93360d9510a30543345da49161257b918891610100900460ff1690612f52565b60405180910390a15050505050565b6003805490600061259a8361319c565b90915550506003546000818152600860205260409020826125b9574292505b6000868686866040516020016125d29493929190612c73565b60408051601f1981840301815291815281516020928301206000818152600984529182208054600181810183558285529484200187905591819052905490925011156126a4576000818152600960205260408120805461263490600290613107565b8154811061265257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050620151806008600083815260200190815260200160002060050154426126859190613107565b106126a25760405162461bcd60e51b815260040161044f90612f04565b505b6000818152600960205260408120546126bf90600190613107565b6126ca90600261301a565b6126dc90678ac7230489e800006130e8565b6001546040516323b872dd60e01b8152336004820152306024820152604481018390529192506001600160a01b0316906323b872dd90606401602060405180830381600087803b15801561272f57600080fd5b505af1158015612743573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127679190612a39565b6127a65760405162461bcd60e51b815260206004820152601060248201526f119959481b5d5cdd081899481c185a5960821b604482015260640161044f565b81835560008281526009602090815260409091205460018501554260028501554360038501556004840182905586516127e791601386019190890190612881565b506014830180546001600160a01b038a166401000000000277ffffffffffffffffffffffffffffffffffffffffffffffff1990911660e08a901c171790556015830180546001600160a01b031916331790556040517f03cd1db94c84fbf802bb289f9fec190fc43fcb105eee5554433e8d642ceab1189061286f908a908a908a908990612d95565b60405180910390a15050505050505050565b82805461288d90613161565b90600052602060002090601f0160209004810192826128af57600085556128f5565b82601f106128c857805160ff19168380011785556128f5565b828001600101855582156128f5579182015b828111156128f55782518255916020019190600101906128da565b50612901929150612942565b5090565b6040518061022001604052806011906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b5b808211156129015760008155600101612943565b600060208284031215612968578081fd5b8135612973816131e3565b9392505050565b60006020828403121561298b578081fd5b8151612973816131e3565b600080604083850312156129a8578081fd5b82356129b3816131e3565b915060208301356129c3816131fb565b809150509250929050565b6000806000606084860312156129e2578081fd5b83356129ed816131e3565b925060208401356129fd816131fb565b929592945050506040919091013590565b60008060408385031215612a20578182fd5b8235612a2b816131e3565b946020939093013593505050565b600060208284031215612a4a578081fd5b8151612973816131fb565b600060208284031215612a66578081fd5b5035919050565b60008060408385031215612a7f578182fd5b50508035926020909101359150565b600060208284031215612a9f578081fd5b815167ffffffffffffffff80821115612ab6578283fd5b818401915084601f830112612ac9578283fd5b815181811115612adb57612adb6131cd565b604051601f8201601f19908116603f01168101908382118183101715612b0357612b036131cd565b81604052828152876020848701011115612b1b578586fd5b612b2c83602083016020880161311e565b979650505050505050565b600060208284031215612b48578081fd5b5051919050565b60008060408385031215612b61578182fd5b8235915060208301356129c3816131e3565b600080600060608486031215612b87578283fd5b833592506020840135612b99816131fb565b91506040840135612ba9816131fb565b809150509250925092565b600080600080600060a08688031215612bcb578081fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b8060005b6002811015612c1f5781516001600160a01b0316845260209384019390910190600101612bf7565b50505050565b60008151808452612c3d81602086016020860161311e565b601f01601f19169290920160200192915050565b60038110612c6f57634e487b7160e01b600052602160045260246000fd5b9052565b606085901b6bffffffffffffffffffffffff191681526001600160e01b0319841660148201528251600090612caf81601885016020880161311e565b6018920191820192909252603801949350505050565b6001600160e01b03198316815281546000906004908290600181811c9080831680612cf157607f831692505b6020808410821415612d1057634e487b7160e01b885260228752602488fd5b818015612d245760018114612d3957612d69565b60ff1986168a890152848a0188019650612d69565b60008b815260209020895b86811015612d5f5781548c82018b0152908501908301612d44565b505087858b010196505b50949a9950505050505050505050565b60008251612d8b81846020870161311e565b9190910192915050565b60006001600160a01b038616825263ffffffff60e01b8516602083015260806040830152612dc66080830185612c25565b905082606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e0f57835183529284019291840191600101612df3565b50909695505050505050565b600061032089835260208084018a845b6011811015612e4857815183529183019190830190600101612e2b565b505050610240840189845b6002811015612e72578151151583529183019190830190600101612e53565b50505050612e84610280840188612c51565b806102a0840152612e9781840187612c25565b915050612eb16102c08301856001600160e01b0319169052565b612ebf6102e0830184612bf3565b98975050505050505050565b600085825284602083015260806040830152612eea6080830185612c25565b90506001600160a01b038316606083015295945050505050565b6020808252602e908201527f4e6577206469737075746520726f756e64206d7573742062652073746172746560408201526d642077697468696e20612064617960901b606082015260800190565b828152604081016129736020830184612c51565b84815260808101612f7a6020830186612c51565b6001600160a01b03808516604084015280841660608401525095945050505050565b60008219821115612faf57612faf6131b7565b500190565b600082612fcf57634e487b7160e01b81526012600452602481fd5b500490565b80825b6001808611612fe65750613011565b818704821115612ff857612ff86131b7565b8086161561300557918102915b9490941c938002612fd7565b94509492505050565b6000612973600019848460008261303357506001612973565b8161304057506000612973565b816001811461305657600281146130605761308d565b6001915050612973565b60ff841115613071576130716131b7565b6001841b915084821115613087576130876131b7565b50612973565b5060208310610133831016604e8410600b84101617156130c0575081810a838111156130bb576130bb6131b7565b612973565b6130cd8484846001612fd4565b8086048211156130df576130df6131b7565b02949350505050565b6000816000190483118215151615613102576131026131b7565b500290565b600082821015613119576131196131b7565b500390565b60005b83811015613139578181015183820152602001613121565b83811115612c1f5750506000910152565b600081613159576131596131b7565b506000190190565b600181811c9082168061317557607f821691505b6020821081141561319657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156131b0576131b06131b7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146131f857600080fd5b50565b80151581146131f857600080fdfea26469706673582212200e66ea4a5edfc6ebd8a2364676a30b97a0e04b0be80b6d19a89932b9eba6e74364736f6c63430008030033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000041b66dd93b03e89d29114a7613a6f9f0d4f401780000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000080fc34a2f9ffe86f41580f47368289c402dec660
-----Decoded View---------------
Arg [0] : _tellor (address): 0x41b66dd93b03e89D29114a7613A6f9f0d4F40178
Arg [1] : _disputeFee (uint256): 5000000000000000000
Arg [2] : _teamMultisig (address): 0x80fc34a2f9FfE86F41580F47368289C402DEc660
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000041b66dd93b03e89d29114a7613a6f9f0d4f40178
Arg [1] : 0000000000000000000000000000000000000000000000004563918244f40000
Arg [2] : 00000000000000000000000080fc34a2f9ffe86f41580f47368289c402dec660
Loading...
Loading
[ Download: CSV Export ]
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.