Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract contains unverified libraries: TellorTransfer, TellorDispute, TellorStake, TellorLibrary
Contract Name:
Tellor
Compiler Version
v0.5.8+commit.23d335f2
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-08-01 */ pragma solidity ^0.5.0; /** * @title Tellor Transfer * @dev Contais the methods related to transfers and ERC20. Tellor.sol and TellorGetters.sol * reference this library for function's logic. */ library TellorTransfer { using SafeMath for uint256; event Approval(address indexed _owner, address indexed _spender, uint256 _value);//ERC20 Approval event event Transfer(address indexed _from, address indexed _to, uint256 _value);//ERC20 Transfer Event /*Functions*/ /** * @dev Allows for a transfer of tokens to _to * @param _to The address to send tokens to * @param _amount The amount of tokens to send * @return true if transfer is successful */ function transfer(TellorStorage.TellorStorageStruct storage self, address _to, uint256 _amount) public returns (bool success) { doTransfer(self,msg.sender, _to, _amount); return true; } /** * @notice Send _amount tokens to _to from _from on the condition it * is approved by _from * @param _from The address holding the tokens being transferred * @param _to The address of the recipient * @param _amount The amount of tokens to be transferred * @return True if the transfer was successful */ function transferFrom(TellorStorage.TellorStorageStruct storage self, address _from, address _to, uint256 _amount) public returns (bool success) { require(self.allowed[_from][msg.sender] >= _amount); self.allowed[_from][msg.sender] -= _amount; doTransfer(self,_from, _to, _amount); return true; } /** * @dev This function approves a _spender an _amount of tokens to use * @param _spender address * @param _amount amount the spender is being approved for * @return true if spender appproved successfully */ function approve(TellorStorage.TellorStorageStruct storage self, address _spender, uint _amount) public returns (bool) { require(allowedToTrade(self,msg.sender,_amount)); require(_spender != address(0)); self.allowed[msg.sender][_spender] = _amount; emit Approval(msg.sender, _spender, _amount); return true; } /** * @param _user address of party with the balance * @param _spender address of spender of parties said balance * @return Returns the remaining allowance of tokens granted to the _spender from the _user */ function allowance(TellorStorage.TellorStorageStruct storage self,address _user, address _spender) public view returns (uint) { return self.allowed[_user][_spender]; } /** * @dev Completes POWO transfers by updating the balances on the current block number * @param _from address to transfer from * @param _to addres to transfer to * @param _amount to transfer */ function doTransfer(TellorStorage.TellorStorageStruct storage self, address _from, address _to, uint _amount) public { require(_amount > 0); require(_to != address(0)); require(allowedToTrade(self,_from,_amount)); //allowedToTrade checks the stakeAmount is removed from balance if the _user is staked uint previousBalance = balanceOfAt(self,_from, block.number); updateBalanceAtNow(self.balances[_from], previousBalance - _amount); previousBalance = balanceOfAt(self,_to, block.number); require(previousBalance + _amount >= previousBalance); // Check for overflow updateBalanceAtNow(self.balances[_to], previousBalance + _amount); emit Transfer(_from, _to, _amount); } /** * @dev Gets balance of owner specified * @param _user is the owner address used to look up the balance * @return Returns the balance associated with the passed in _user */ function balanceOf(TellorStorage.TellorStorageStruct storage self,address _user) public view returns (uint) { return balanceOfAt(self,_user, block.number); } /** * @dev Queries the balance of _user at a specific _blockNumber * @param _user The address from which the balance will be retrieved * @param _blockNumber The block number when the balance is queried * @return The balance at _blockNumber specified */ function balanceOfAt(TellorStorage.TellorStorageStruct storage self,address _user, uint _blockNumber) public view returns (uint) { if ((self.balances[_user].length == 0) || (self.balances[_user][0].fromBlock > _blockNumber)) { return 0; } else { return getBalanceAt(self.balances[_user], _blockNumber); } } /** * @dev Getter for balance for owner on the specified _block number * @param checkpoints gets the mapping for the balances[owner] * @param _block is the block number to search the balance on * @return the balance at the checkpoint */ function getBalanceAt(TellorStorage.Checkpoint[] storage checkpoints, uint _block) view public returns (uint) { if (checkpoints.length == 0) return 0; if (_block >= checkpoints[checkpoints.length-1].fromBlock) return checkpoints[checkpoints.length-1].value; if (_block < checkpoints[0].fromBlock) return 0; // Binary search of the value in the array uint min = 0; uint max = checkpoints.length-1; while (max > min) { uint mid = (max + min + 1)/ 2; if (checkpoints[mid].fromBlock<=_block) { min = mid; } else { max = mid-1; } } return checkpoints[min].value; } /** * @dev This function returns whether or not a given user is allowed to trade a given amount * and removing the staked amount from their balance if they are staked * @param _user address of user * @param _amount to check if the user can spend * @return true if they are allowed to spend the amount being checked */ function allowedToTrade(TellorStorage.TellorStorageStruct storage self,address _user,uint _amount) public view returns(bool) { if(self.stakerDetails[_user].currentStatus >0){ //Removes the stakeAmount from balance if the _user is staked if(balanceOf(self,_user).sub(self.uintVars[keccak256("stakeAmount")]).sub(_amount) >= 0){ return true; } } else if(balanceOf(self,_user).sub(_amount) >= 0){ return true; } return false; } /** * @dev Updates balance for from and to on the current block number via doTransfer * @param checkpoints gets the mapping for the balances[owner] * @param _value is the new balance */ function updateBalanceAtNow(TellorStorage.Checkpoint[] storage checkpoints, uint _value) public { if ((checkpoints.length == 0) || (checkpoints[checkpoints.length -1].fromBlock < block.number)) { TellorStorage.Checkpoint storage newCheckPoint = checkpoints[ checkpoints.length++ ]; newCheckPoint.fromBlock = uint128(block.number); newCheckPoint.value = uint128(_value); } else { TellorStorage.Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1]; oldCheckPoint.value = uint128(_value); } } } /** * @title Tellor Dispute * @dev Contais the methods related to disputes. Tellor.sol references this library for function's logic. */ library TellorDispute { using SafeMath for uint256; using SafeMath for int256; event NewDispute(uint indexed _disputeId, uint indexed _requestId, uint _timestamp, address _miner);//emitted when a new dispute is initialized event Voted(uint indexed _disputeID, bool _position, address indexed _voter);//emitted when a new vote happens event DisputeVoteTallied(uint indexed _disputeID, int _result,address indexed _reportedMiner,address _reportingParty, bool _active);//emitted upon dispute tally event NewTellorAddress(address _newTellor); //emmited when a proposed fork is voted true /*Functions*/ /** * @dev Helps initialize a dispute by assigning it a disputeId * when a miner returns a false on the validate array(in Tellor.ProofOfWork) it sends the * invalidated value information to POS voting * @param _requestId being disputed * @param _timestamp being disputed * @param _minerIndex the index of the miner that submitted the value being disputed. Since each official value * requires 5 miners to submit a value. */ function beginDispute(TellorStorage.TellorStorageStruct storage self,uint _requestId, uint _timestamp,uint _minerIndex) public { TellorStorage.Request storage _request = self.requestDetails[_requestId]; //require that no more than a day( (24 hours * 60 minutes)/10minutes=144 blocks) has gone by since the value was "mined" require(block.number- _request.minedBlockNum[_timestamp]<= 144); require(_request.minedBlockNum[_timestamp] > 0); require(_minerIndex < 5); //_miner is the miner being disputed. For every mined value 5 miners are saved in an array and the _minerIndex //provided by the party initiating the dispute address _miner = _request.minersByValue[_timestamp][_minerIndex]; bytes32 _hash = keccak256(abi.encodePacked(_miner,_requestId,_timestamp)); //Ensures that a dispute is not already open for the that miner, requestId and timestamp require(self.disputeIdByDisputeHash[_hash] == 0); TellorTransfer.doTransfer(self, msg.sender,address(this), self.uintVars[keccak256("disputeFee")]); //Increase the dispute count by 1 self.uintVars[keccak256("disputeCount")] = self.uintVars[keccak256("disputeCount")] + 1; //Sets the new disputeCount as the disputeId uint disputeId = self.uintVars[keccak256("disputeCount")]; //maps the dispute hash to the disputeId self.disputeIdByDisputeHash[_hash] = disputeId; //maps the dispute to the Dispute struct self.disputesById[disputeId] = TellorStorage.Dispute({ hash:_hash, isPropFork: false, reportedMiner: _miner, reportingParty: msg.sender, proposedForkAddress:address(0), executed: false, disputeVotePassed: false, tally: 0 }); //Saves all the dispute variables for the disputeId self.disputesById[disputeId].disputeUintVars[keccak256("requestId")] = _requestId; self.disputesById[disputeId].disputeUintVars[keccak256("timestamp")] = _timestamp; self.disputesById[disputeId].disputeUintVars[keccak256("value")] = _request.valuesByTimestamp[_timestamp][_minerIndex]; self.disputesById[disputeId].disputeUintVars[keccak256("minExecutionDate")] = now + 7 days; self.disputesById[disputeId].disputeUintVars[keccak256("blockNumber")] = block.number; self.disputesById[disputeId].disputeUintVars[keccak256("minerSlot")] = _minerIndex; self.disputesById[disputeId].disputeUintVars[keccak256("fee")] = self.uintVars[keccak256("disputeFee")]; //Values are sorted as they come in and the official value is the median of the first five //So the "official value" miner is always minerIndex==2. If the official value is being //disputed, it sets its status to inDispute(currentStatus = 3) so that users are made aware it is under dispute if(_minerIndex == 2){ self.requestDetails[_requestId].inDispute[_timestamp] = true; } self.stakerDetails[_miner].currentStatus = 3; emit NewDispute(disputeId,_requestId,_timestamp,_miner); } /** * @dev Allows token holders to vote * @param _disputeId is the dispute id * @param _supportsDispute is the vote (true=the dispute has basis false = vote against dispute) */ function vote(TellorStorage.TellorStorageStruct storage self, uint _disputeId, bool _supportsDispute) public { TellorStorage.Dispute storage disp = self.disputesById[_disputeId]; //Get the voteWeight or the balance of the user at the time/blockNumber the disupte began uint voteWeight = TellorTransfer.balanceOfAt(self,msg.sender,disp.disputeUintVars[keccak256("blockNumber")]); //Require that the msg.sender has not voted require(disp.voted[msg.sender] != true); //Requre that the user had a balance >0 at time/blockNumber the disupte began require(voteWeight > 0); //ensures miners that are under dispute cannot vote require(self.stakerDetails[msg.sender].currentStatus != 3); //Update user voting status to true disp.voted[msg.sender] = true; //Update the number of votes for the dispute disp.disputeUintVars[keccak256("numberOfVotes")] += 1; //Update the quorum by adding the voteWeight disp.disputeUintVars[keccak256("quorum")] += voteWeight; //If the user supports the dispute increase the tally for the dispute by the voteWeight //otherwise decrease it if (_supportsDispute) { disp.tally = disp.tally.add(int(voteWeight)); } else { disp.tally = disp.tally.sub(int(voteWeight)); } //Let the network know the user has voted on the dispute and their casted vote emit Voted(_disputeId,_supportsDispute,msg.sender); } /** * @dev tallies the votes. * @param _disputeId is the dispute id */ function tallyVotes(TellorStorage.TellorStorageStruct storage self, uint _disputeId) public { TellorStorage.Dispute storage disp = self.disputesById[_disputeId]; TellorStorage.Request storage _request = self.requestDetails[disp.disputeUintVars[keccak256("requestId")]]; //Ensure this has not already been executed/tallied require(disp.executed == false); //Ensure the time for voting has elapsed require(now > disp.disputeUintVars[keccak256("minExecutionDate")]); //If the vote is not a proposed fork if (disp.isPropFork== false){ TellorStorage.StakeInfo storage stakes = self.stakerDetails[disp.reportedMiner]; //If the vote for disputing a value is succesful(disp.tally >0) then unstake the reported // miner and transfer the stakeAmount and dispute fee to the reporting party if (disp.tally > 0 ) { //Changing the currentStatus and startDate unstakes the reported miner and allows for the //transfer of the stakeAmount stakes.currentStatus = 0; stakes.startDate = now -(now % 86400); //Decreases the stakerCount since the miner's stake is being slashed self.uintVars[keccak256("stakerCount")]--; updateDisputeFee(self); //Transfers the StakeAmount from the reporded miner to the reporting party TellorTransfer.doTransfer(self, disp.reportedMiner,disp.reportingParty, self.uintVars[keccak256("stakeAmount")]); //Returns the dispute fee to the reportingParty TellorTransfer.doTransfer(self, address(this),disp.reportingParty,disp.disputeUintVars[keccak256("fee")]); //Set the dispute state to passed/true disp.disputeVotePassed = true; //If the dispute was succeful(miner found guilty) then update the timestamp value to zero //so that users don't use this datapoint if(_request.inDispute[disp.disputeUintVars[keccak256("timestamp")]] == true){ _request.finalValues[disp.disputeUintVars[keccak256("timestamp")]] = 0; } //If the vote for disputing a value is unsuccesful then update the miner status from being on //dispute(currentStatus=3) to staked(currentStatus =1) and tranfer the dispute fee to the miner } else { //Update the miner's current status to staked(currentStatus = 1) stakes.currentStatus = 1; //tranfer the dispute fee to the miner TellorTransfer.doTransfer(self,address(this),disp.reportedMiner,disp.disputeUintVars[keccak256("fee")]); if(_request.inDispute[disp.disputeUintVars[keccak256("timestamp")]] == true){ _request.inDispute[disp.disputeUintVars[keccak256("timestamp")]] = false; } } //If the vote is for a proposed fork require a 20% quorum before excecuting the update to the new tellor contract address } else { if(disp.tally > 0 ){ require(disp.disputeUintVars[keccak256("quorum")] > (self.uintVars[keccak256("total_supply")] * 20 / 100)); self.addressVars[keccak256("tellorContract")] = disp.proposedForkAddress; disp.disputeVotePassed = true; emit NewTellorAddress(disp.proposedForkAddress); } } //update the dispute status to executed disp.executed = true; emit DisputeVoteTallied(_disputeId,disp.tally,disp.reportedMiner,disp.reportingParty,disp.disputeVotePassed); } /** * @dev Allows for a fork to be proposed * @param _propNewTellorAddress address for new proposed Tellor */ function proposeFork(TellorStorage.TellorStorageStruct storage self, address _propNewTellorAddress) public { bytes32 _hash = keccak256(abi.encodePacked(_propNewTellorAddress)); require(self.disputeIdByDisputeHash[_hash] == 0); TellorTransfer.doTransfer(self, msg.sender,address(this), self.uintVars[keccak256("disputeFee")]);//This is the fork fee self.uintVars[keccak256("disputeCount")]++; uint disputeId = self.uintVars[keccak256("disputeCount")]; self.disputeIdByDisputeHash[_hash] = disputeId; self.disputesById[disputeId] = TellorStorage.Dispute({ hash: _hash, isPropFork: true, reportedMiner: msg.sender, reportingParty: msg.sender, proposedForkAddress: _propNewTellorAddress, executed: false, disputeVotePassed: false, tally: 0 }); self.disputesById[disputeId].disputeUintVars[keccak256("blockNumber")] = block.number; self.disputesById[disputeId].disputeUintVars[keccak256("fee")] = self.uintVars[keccak256("disputeFee")]; self.disputesById[disputeId].disputeUintVars[keccak256("minExecutionDate")] = now + 7 days; } /** * @dev this function allows the dispute fee to fluctuate based on the number of miners on the system. * The floor for the fee is 15e18. */ function updateDisputeFee(TellorStorage.TellorStorageStruct storage self) public { //if the number of staked miners divided by the target count of staked miners is less than 1 if(self.uintVars[keccak256("stakerCount")]*1000/self.uintVars[keccak256("targetMiners")] < 1000){ //Set the dispute fee at stakeAmt * (1- stakerCount/targetMiners) //or at the its minimum of 15e18 self.uintVars[keccak256("disputeFee")] = SafeMath.max(15e18,self.uintVars[keccak256("stakeAmount")].mul(1000 - self.uintVars[keccak256("stakerCount")]*1000/self.uintVars[keccak256("targetMiners")])/1000); } else{ //otherwise set the dispute fee at 15e18 (the floor/minimum fee allowed) self.uintVars[keccak256("disputeFee")] = 15e18; } } } /** * itle Tellor Dispute * @dev Contais the methods related to miners staking and unstaking. Tellor.sol * references this library for function's logic. */ library TellorStake { event NewStake(address indexed _sender);//Emits upon new staker event StakeWithdrawn(address indexed _sender);//Emits when a staker is now no longer staked event StakeWithdrawRequested(address indexed _sender);//Emits when a staker begins the 7 day withdraw period /*Functions*/ /** * @dev This function stakes the five initial miners, sets the supply and all the constant variables. * This function is called by the constructor function on TellorMaster.sol */ function init(TellorStorage.TellorStorageStruct storage self) public{ require(self.uintVars[keccak256("decimals")] == 0); //Give this contract 6000 Tellor Tributes so that it can stake the initial 6 miners TellorTransfer.updateBalanceAtNow(self.balances[address(this)], 2**256-1 - 6000e18); // //the initial 5 miner addresses are specfied below // //changed payable[5] to 6 address payable[6] memory _initalMiners = [address(0xE037EC8EC9ec423826750853899394dE7F024fee), address(0xcdd8FA31AF8475574B8909F135d510579a8087d3), address(0xb9dD5AfD86547Df817DA2d0Fb89334A6F8eDd891), address(0x230570cD052f40E14C14a81038c6f3aa685d712B), address(0x3233afA02644CCd048587F8ba6e99b3C00A34DcC), address(0xe010aC6e0248790e08F42d5F697160DEDf97E024)]; //Stake each of the 5 miners specified above for(uint i=0;i<6;i++){//6th miner to allow for dispute //Miner balance is set at 1000e18 at the block that this function is ran TellorTransfer.updateBalanceAtNow(self.balances[_initalMiners[i]],1000e18); newStake(self, _initalMiners[i]); } //update the total suppply self.uintVars[keccak256("total_supply")] += 6000e18;//6th miner to allow for dispute //set Constants self.uintVars[keccak256("decimals")] = 18; self.uintVars[keccak256("targetMiners")] = 200; self.uintVars[keccak256("stakeAmount")] = 1000e18; self.uintVars[keccak256("disputeFee")] = 970e18; self.uintVars[keccak256("timeTarget")]= 600; self.uintVars[keccak256("timeOfLastNewValue")] = now - now % self.uintVars[keccak256("timeTarget")]; self.uintVars[keccak256("difficulty")] = 1; } /** * @dev This function allows stakers to request to withdraw their stake (no longer stake) * once they lock for withdraw(stakes.currentStatus = 2) they are locked for 7 days before they * can withdraw the deposit */ function requestStakingWithdraw(TellorStorage.TellorStorageStruct storage self) public { TellorStorage.StakeInfo storage stakes = self.stakerDetails[msg.sender]; //Require that the miner is staked require(stakes.currentStatus == 1); //Change the miner staked to locked to be withdrawStake stakes.currentStatus = 2; //Change the startDate to now since the lock up period begins now //and the miner can only withdraw 7 days later from now(check the withdraw function) stakes.startDate = now -(now % 86400); //Reduce the staker count self.uintVars[keccak256("stakerCount")] -= 1; TellorDispute.updateDisputeFee(self); emit StakeWithdrawRequested(msg.sender); } /** * @dev This function allows users to withdraw their stake after a 7 day waiting period from request */ function withdrawStake(TellorStorage.TellorStorageStruct storage self) public { TellorStorage.StakeInfo storage stakes = self.stakerDetails[msg.sender]; //Require the staker has locked for withdraw(currentStatus ==2) and that 7 days have //passed by since they locked for withdraw require(now - (now % 86400) - stakes.startDate >= 7 days); require(stakes.currentStatus == 2); stakes.currentStatus = 0; emit StakeWithdrawn(msg.sender); } /** * @dev This function allows miners to deposit their stake. */ function depositStake(TellorStorage.TellorStorageStruct storage self) public { newStake(self, msg.sender); //self adjusting disputeFee TellorDispute.updateDisputeFee(self); } /** * @dev This function is used by the init function to succesfully stake the initial 5 miners. * The function updates their status/state and status start date so they are locked it so they can't withdraw * and updates the number of stakers in the system. */ function newStake(TellorStorage.TellorStorageStruct storage self, address staker) internal { require(TellorTransfer.balanceOf(self,staker) >= self.uintVars[keccak256("stakeAmount")]); //Ensure they can only stake if they are not currrently staked or if their stake time frame has ended //and they are currently locked for witdhraw require(self.stakerDetails[staker].currentStatus == 0 || self.stakerDetails[staker].currentStatus == 2); self.uintVars[keccak256("stakerCount")] += 1; self.stakerDetails[staker] = TellorStorage.StakeInfo({ currentStatus: 1, //this resets their stake start date to today startDate: now - (now % 86400) }); emit NewStake(staker); } } //Slightly modified SafeMath library - includes a min and max function, removes useless div function library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } function add(int256 a, int256 b) internal pure returns (int256 c) { if(b > 0){ c = a + b; assert(c >= a); } else{ c = a + b; assert(c <= a); } } function max(uint a, uint b) internal pure returns (uint256) { return a > b ? a : b; } function max(int256 a, int256 b) internal pure returns (uint256) { return a > b ? uint(a) : uint(b); } function min(uint a, uint b) internal pure returns (uint256) { return a < b ? a : b; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; assert(a == 0 || c / a == b); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function sub(int256 a, int256 b) internal pure returns (int256 c) { if(b > 0){ c = a - b; assert(c <= a); } else{ c = a - b; assert(c >= a); } } } /** * @title Tellor Oracle Storage Library * @dev Contains all the variables/structs used by Tellor */ library TellorStorage { //Internal struct for use in proof-of-work submission struct Details { uint value; address miner; } struct Dispute { bytes32 hash;//unique hash of dispute: keccak256(_miner,_requestId,_timestamp) int tally;//current tally of votes for - against measure bool executed;//is the dispute settled bool disputeVotePassed;//did the vote pass? bool isPropFork; //true for fork proposal NEW address reportedMiner; //miner who alledgedly submitted the 'bad value' will get disputeFee if dispute vote fails address reportingParty;//miner reporting the 'bad value'-pay disputeFee will get reportedMiner's stake if dispute vote passes address proposedForkAddress;//new fork address (if fork proposal) mapping(bytes32 => uint) disputeUintVars; //Each of the variables below is saved in the mapping disputeUintVars for each disputeID //e.g. TellorStorageStruct.DisputeById[disputeID].disputeUintVars[keccak256("requestId")] //These are the variables saved in this mapping: // uint keccak256("requestId");//apiID of disputed value // uint keccak256("timestamp");//timestamp of distputed value // uint keccak256("value"); //the value being disputed // uint keccak256("minExecutionDate");//7 days from when dispute initialized // uint keccak256("numberOfVotes");//the number of parties who have voted on the measure // uint keccak256("blockNumber");// the blocknumber for which votes will be calculated from // uint keccak256("minerSlot"); //index in dispute array // uint keccak256("quorum"); //quorum for dispute vote NEW // uint keccak256("fee"); //fee paid corresponding to dispute mapping (address => bool) voted; //mapping of address to whether or not they voted } struct StakeInfo { uint currentStatus;//0-not Staked, 1=Staked, 2=LockedForWithdraw 3= OnDispute uint startDate; //stake start date } //Internal struct to allow balances to be queried by blocknumber for voting purposes struct Checkpoint { uint128 fromBlock;// fromBlock is the block number that the value was generated from uint128 value;// value is the amount of tokens at a specific block number } struct Request { string queryString;//id to string api string dataSymbol;//short name for api request bytes32 queryHash;//hash of api string and granularity e.g. keccak256(abi.encodePacked(_sapi,_granularity)) uint[] requestTimestamps; //array of all newValueTimestamps requested mapping(bytes32 => uint) apiUintVars; //Each of the variables below is saved in the mapping apiUintVars for each api request //e.g. requestDetails[_requestId].apiUintVars[keccak256("totalTip")] //These are the variables saved in this mapping: // uint keccak256("granularity"); //multiplier for miners // uint keccak256("requestQPosition"); //index in requestQ // uint keccak256("totalTip");//bonus portion of payout mapping(uint => uint) minedBlockNum;//[apiId][minedTimestamp]=>block.number mapping(uint => uint) finalValues;//This the time series of finalValues stored by the contract where uint UNIX timestamp is mapped to value mapping(uint => bool) inDispute;//checks if API id is in dispute or finalized. mapping(uint => address[5]) minersByValue; mapping(uint => uint[5])valuesByTimestamp; } struct TellorStorageStruct { bytes32 currentChallenge; //current challenge to be solved uint[51] requestQ; //uint50 array of the top50 requests by payment amount uint[] newValueTimestamps; //array of all timestamps requested Details[5] currentMiners; //This struct is for organizing the five mined values to find the median mapping(bytes32 => address) addressVars; //Address fields in the Tellor contract are saved the addressVars mapping //e.g. addressVars[keccak256("tellorContract")] = address //These are the variables saved in this mapping: // address keccak256("tellorContract");//Tellor address // address keccak256("_owner");//Tellor Owner address // address keccak256("_deity");//Tellor Owner that can do things at will mapping(bytes32 => uint) uintVars; //uint fields in the Tellor contract are saved the uintVars mapping //e.g. uintVars[keccak256("decimals")] = uint //These are the variables saved in this mapping: // keccak256("decimals"); //18 decimal standard ERC20 // keccak256("disputeFee");//cost to dispute a mined value // keccak256("disputeCount");//totalHistoricalDisputes // keccak256("total_supply"); //total_supply of the token in circulation // keccak256("stakeAmount");//stakeAmount for miners (we can cut gas if we just hardcode it in...or should it be variable?) // keccak256("stakerCount"); //number of parties currently staked // keccak256("timeOfLastNewValue"); // time of last challenge solved // keccak256("difficulty"); // Difficulty of current block // keccak256("currentTotalTips"); //value of highest api/timestamp PayoutPool // keccak256("currentRequestId"); //API being mined--updates with the ApiOnQ Id // keccak256("requestCount"); // total number of requests through the system // keccak256("slotProgress");//Number of miners who have mined this value so far // keccak256("miningReward");//Mining Reward in PoWo tokens given to all miners per value // keccak256("timeTarget"); //The time between blocks (mined Oracle values) mapping(bytes32 => mapping(address=>bool)) minersByChallenge;//This is a boolean that tells you if a given challenge has been completed by a given miner mapping(uint => uint) requestIdByTimestamp;//minedTimestamp to apiId mapping(uint => uint) requestIdByRequestQIndex; //link from payoutPoolIndex (position in payout pool array) to apiId mapping(uint => Dispute) disputesById;//disputeId=> Dispute details mapping (address => Checkpoint[]) balances; //balances of a party given blocks mapping(address => mapping (address => uint)) allowed; //allowance for a given party and approver mapping(address => StakeInfo) stakerDetails;//mapping from a persons address to their staking info mapping(uint => Request) requestDetails;//mapping of apiID to details mapping(bytes32 => uint) requestIdByQueryHash;// api bytes32 gets an id = to count of requests array mapping(bytes32 => uint) disputeIdByDisputeHash;//maps a hash to an ID for each dispute } } //Functions for retrieving min and Max in 51 length array (requestQ) //Taken partly from: https://github.com/modular-network/ethereum-libraries-array-utils/blob/master/contracts/Array256Lib.sol library Utilities{ /** * @dev Returns the minimum value in an array. */ function getMax(uint[51] memory data) internal pure returns(uint256 max,uint256 maxIndex) { max = data[1]; maxIndex; for(uint i=1;i < data.length;i++){ if(data[i] > max){ max = data[i]; maxIndex = i; } } } /** * @dev Returns the minimum value in an array. */ function getMin(uint[51] memory data) internal pure returns(uint256 min,uint256 minIndex) { minIndex = data.length - 1; min = data[minIndex]; for(uint i = data.length-1;i > 0;i--) { if(data[i] < min) { min = data[i]; minIndex = i; } } } // /// @dev Returns the minimum value and position in an array. // //@note IT IGNORES THE 0 INDEX // function getMin(uint[51] memory arr) internal pure returns (uint256 min, uint256 minIndex) { // assembly { // minIndex := 50 // min := mload(add(arr, mul(minIndex , 0x20))) // for {let i := 49 } gt(i,0) { i := sub(i, 1) } { // let item := mload(add(arr, mul(i, 0x20))) // if lt(item,min){ // min := item // minIndex := i // } // } // } // } // function getMax(uint256[51] memory arr) internal pure returns (uint256 max, uint256 maxIndex) { // assembly { // for { let i := 0 } lt(i,51) { i := add(i, 1) } { // let item := mload(add(arr, mul(i, 0x20))) // if lt(max, item) { // max := item // maxIndex := i // } // } // } // } } /** * @title Tellor Getters Library * @dev This is the getter library for all variables in the Tellor Tributes system. TellorGetters references this * libary for the getters logic */ library TellorGettersLibrary{ using SafeMath for uint256; event NewTellorAddress(address _newTellor); //emmited when a proposed fork is voted true /*Functions*/ //The next two functions are onlyOwner functions. For Tellor to be truly decentralized, we will need to transfer the Deity to the 0 address. //Only needs to be in library /** * @dev This function allows us to set a new Deity (or remove it) * @param _newDeity address of the new Deity of the tellor system */ function changeDeity(TellorStorage.TellorStorageStruct storage self, address _newDeity) internal{ require(self.addressVars[keccak256("_deity")] == msg.sender); self.addressVars[keccak256("_deity")] =_newDeity; } //Only needs to be in library /** * @dev This function allows the deity to upgrade the Tellor System * @param _tellorContract address of new updated TellorCore contract */ function changeTellorContract(TellorStorage.TellorStorageStruct storage self,address _tellorContract) internal{ require(self.addressVars[keccak256("_deity")] == msg.sender); self.addressVars[keccak256("tellorContract")]= _tellorContract; emit NewTellorAddress(_tellorContract); } /*Tellor Getters*/ /** * @dev This function tells you if a given challenge has been completed by a given miner * @param _challenge the challenge to search for * @param _miner address that you want to know if they solved the challenge * @return true if the _miner address provided solved the */ function didMine(TellorStorage.TellorStorageStruct storage self, bytes32 _challenge,address _miner) internal view returns(bool){ return self.minersByChallenge[_challenge][_miner]; } /** * @dev Checks if an address voted in a dispute * @param _disputeId to look up * @param _address of voting party to look up * @return bool of whether or not party voted */ function didVote(TellorStorage.TellorStorageStruct storage self,uint _disputeId, address _address) internal view returns(bool){ return self.disputesById[_disputeId].voted[_address]; } /** * @dev allows Tellor to read data from the addressVars mapping * @param _data is the keccak256("variable_name") of the variable that is being accessed. * These are examples of how the variables are saved within other functions: * addressVars[keccak256("_owner")] * addressVars[keccak256("tellorContract")] */ function getAddressVars(TellorStorage.TellorStorageStruct storage self, bytes32 _data) view internal returns(address){ return self.addressVars[_data]; } /** * @dev Gets all dispute variables * @param _disputeId to look up * @return bytes32 hash of dispute * @return bool executed where true if it has been voted on * @return bool disputeVotePassed * @return bool isPropFork true if the dispute is a proposed fork * @return address of reportedMiner * @return address of reportingParty * @return address of proposedForkAddress * @return uint of requestId * @return uint of timestamp * @return uint of value * @return uint of minExecutionDate * @return uint of numberOfVotes * @return uint of blocknumber * @return uint of minerSlot * @return uint of quorum * @return uint of fee * @return int count of the current tally */ function getAllDisputeVars(TellorStorage.TellorStorageStruct storage self,uint _disputeId) internal view returns(bytes32, bool, bool, bool, address, address, address,uint[9] memory, int){ TellorStorage.Dispute storage disp = self.disputesById[_disputeId]; return(disp.hash,disp.executed, disp.disputeVotePassed, disp.isPropFork, disp.reportedMiner, disp.reportingParty,disp.proposedForkAddress,[disp.disputeUintVars[keccak256("requestId")], disp.disputeUintVars[keccak256("timestamp")], disp.disputeUintVars[keccak256("value")], disp.disputeUintVars[keccak256("minExecutionDate")], disp.disputeUintVars[keccak256("numberOfVotes")], disp.disputeUintVars[keccak256("blockNumber")], disp.disputeUintVars[keccak256("minerSlot")], disp.disputeUintVars[keccak256("quorum")],disp.disputeUintVars[keccak256("fee")]],disp.tally); } /** * @dev Getter function for variables for the requestId being currently mined(currentRequestId) * @return current challenge, curretnRequestId, level of difficulty, api/query string, and granularity(number of decimals requested), total tip for the request */ function getCurrentVariables(TellorStorage.TellorStorageStruct storage self) internal view returns(bytes32, uint, uint,string memory,uint,uint){ return (self.currentChallenge,self.uintVars[keccak256("currentRequestId")],self.uintVars[keccak256("difficulty")],self.requestDetails[self.uintVars[keccak256("currentRequestId")]].queryString,self.requestDetails[self.uintVars[keccak256("currentRequestId")]].apiUintVars[keccak256("granularity")],self.requestDetails[self.uintVars[keccak256("currentRequestId")]].apiUintVars[keccak256("totalTip")]); } /** * @dev Checks if a given hash of miner,requestId has been disputed * @param _hash is the sha256(abi.encodePacked(_miners[2],_requestId)); * @return uint disputeId */ function getDisputeIdByDisputeHash(TellorStorage.TellorStorageStruct storage self,bytes32 _hash) internal view returns(uint){ return self.disputeIdByDisputeHash[_hash]; } /** * @dev Checks for uint variables in the disputeUintVars mapping based on the disuputeId * @param _disputeId is the dispute id; * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the disputeUintVars under the Dispute struct * @return uint value for the bytes32 data submitted */ function getDisputeUintVars(TellorStorage.TellorStorageStruct storage self,uint _disputeId,bytes32 _data) internal view returns(uint){ return self.disputesById[_disputeId].disputeUintVars[_data]; } /** * @dev Gets the a value for the latest timestamp available * @return value for timestamp of last proof of work submited * @return true if the is a timestamp for the lastNewValue */ function getLastNewValue(TellorStorage.TellorStorageStruct storage self) internal view returns(uint,bool){ return (retrieveData(self,self.requestIdByTimestamp[self.uintVars[keccak256("timeOfLastNewValue")]], self.uintVars[keccak256("timeOfLastNewValue")]),true); } /** * @dev Gets the a value for the latest timestamp available * @param _requestId being requested * @return value for timestamp of last proof of work submited and if true if it exist or 0 and false if it doesn't */ function getLastNewValueById(TellorStorage.TellorStorageStruct storage self,uint _requestId) internal view returns(uint,bool){ TellorStorage.Request storage _request = self.requestDetails[_requestId]; if(_request.requestTimestamps.length > 0){ return (retrieveData(self,_requestId,_request.requestTimestamps[_request.requestTimestamps.length - 1]),true); } else{ return (0,false); } } /** * @dev Gets blocknumber for mined timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up blocknumber * @return uint of the blocknumber which the dispute was mined */ function getMinedBlockNum(TellorStorage.TellorStorageStruct storage self,uint _requestId, uint _timestamp) internal view returns(uint){ return self.requestDetails[_requestId].minedBlockNum[_timestamp]; } /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up miners for * @return the 5 miners' addresses */ function getMinersByRequestIdAndTimestamp(TellorStorage.TellorStorageStruct storage self, uint _requestId, uint _timestamp) internal view returns(address[5] memory){ return self.requestDetails[_requestId].minersByValue[_timestamp]; } /** * @dev Get the name of the token * @return string of the token name */ function getName(TellorStorage.TellorStorageStruct storage self) internal pure returns(string memory){ return "Tellor Tributes"; } /** * @dev Counts the number of values that have been submited for the request * if called for the currentRequest being mined it can tell you how many miners have submitted a value for that * request so far * @param _requestId the requestId to look up * @return uint count of the number of values received for the requestId */ function getNewValueCountbyRequestId(TellorStorage.TellorStorageStruct storage self, uint _requestId) internal view returns(uint){ return self.requestDetails[_requestId].requestTimestamps.length; } /** * @dev Getter function for the specified requestQ index * @param _index to look up in the requestQ array * @return uint of reqeuestId */ function getRequestIdByRequestQIndex(TellorStorage.TellorStorageStruct storage self, uint _index) internal view returns(uint){ require(_index <= 50); return self.requestIdByRequestQIndex[_index]; } /** * @dev Getter function for requestId based on timestamp * @param _timestamp to check requestId * @return uint of reqeuestId */ function getRequestIdByTimestamp(TellorStorage.TellorStorageStruct storage self, uint _timestamp) internal view returns(uint){ return self.requestIdByTimestamp[_timestamp]; } /** * @dev Getter function for requestId based on the qeuaryHash * @param _queryHash hash(of string api and granularity) to check if a request already exists * @return uint requestId */ function getRequestIdByQueryHash(TellorStorage.TellorStorageStruct storage self, bytes32 _queryHash) internal view returns(uint){ return self.requestIdByQueryHash[_queryHash]; } /** * @dev Getter function for the requestQ array * @return the requestQ arrray */ function getRequestQ(TellorStorage.TellorStorageStruct storage self) view internal returns(uint[51] memory){ return self.requestQ; } /** * @dev Allowes access to the uint variables saved in the apiUintVars under the requestDetails struct * for the requestId specified * @param _requestId to look up * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the apiUintVars under the requestDetails struct * @return uint value of the apiUintVars specified in _data for the requestId specified */ function getRequestUintVars(TellorStorage.TellorStorageStruct storage self,uint _requestId,bytes32 _data) internal view returns(uint){ return self.requestDetails[_requestId].apiUintVars[_data]; } /** * @dev Gets the API struct variables that are not mappings * @param _requestId to look up * @return string of api to query * @return string of symbol of api to query * @return bytes32 hash of string * @return bytes32 of the granularity(decimal places) requested * @return uint of index in requestQ array * @return uint of current payout/tip for this requestId */ function getRequestVars(TellorStorage.TellorStorageStruct storage self,uint _requestId) internal view returns(string memory,string memory, bytes32,uint, uint, uint) { TellorStorage.Request storage _request = self.requestDetails[_requestId]; return (_request.queryString,_request.dataSymbol,_request.queryHash, _request.apiUintVars[keccak256("granularity")],_request.apiUintVars[keccak256("requestQPosition")],_request.apiUintVars[keccak256("totalTip")]); } /** * @dev This function allows users to retireve all information about a staker * @param _staker address of staker inquiring about * @return uint current state of staker * @return uint startDate of staking */ function getStakerInfo(TellorStorage.TellorStorageStruct storage self,address _staker) internal view returns(uint,uint){ return (self.stakerDetails[_staker].currentStatus,self.stakerDetails[_staker].startDate); } /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestampt to look up miners for * @return address[5] array of 5 addresses ofminers that mined the requestId */ function getSubmissionsByTimestamp(TellorStorage.TellorStorageStruct storage self, uint _requestId, uint _timestamp) internal view returns(uint[5] memory){ return self.requestDetails[_requestId].valuesByTimestamp[_timestamp]; } /** * @dev Get the symbol of the token * @return string of the token symbol */ function getSymbol(TellorStorage.TellorStorageStruct storage self) internal pure returns(string memory){ return "TT"; } /** * @dev Gets the timestamp for the value based on their index * @param _requestID is the requestId to look up * @param _index is the value index to look up * @return uint timestamp */ function getTimestampbyRequestIDandIndex(TellorStorage.TellorStorageStruct storage self,uint _requestID, uint _index) internal view returns(uint){ return self.requestDetails[_requestID].requestTimestamps[_index]; } /** * @dev Getter for the variables saved under the TellorStorageStruct uintVars variable * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the uintVars under the TellorStorageStruct struct * This is an example of how data is saved into the mapping within other functions: * self.uintVars[keccak256("stakerCount")] * @return uint of specified variable */ function getUintVar(TellorStorage.TellorStorageStruct storage self,bytes32 _data) view internal returns(uint){ return self.uintVars[_data]; } /** * @dev Getter function for next requestId on queue/request with highest payout at time the function is called * @return onDeck/info on request with highest payout-- RequestId, Totaltips, and API query string */ function getVariablesOnDeck(TellorStorage.TellorStorageStruct storage self) internal view returns(uint, uint,string memory){ uint newRequestId = getTopRequestID(self); return (newRequestId,self.requestDetails[newRequestId].apiUintVars[keccak256("totalTip")],self.requestDetails[newRequestId].queryString); } /** * @dev Getter function for the request with highest payout. This function is used within the getVariablesOnDeck function * @return uint _requestId of request with highest payout at the time the function is called */ function getTopRequestID(TellorStorage.TellorStorageStruct storage self) internal view returns(uint _requestId){ uint _max; uint _index; (_max,_index) = Utilities.getMax(self.requestQ); _requestId = self.requestIdByRequestQIndex[_index]; } /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up miners for * @return bool true if requestId/timestamp is under dispute */ function isInDispute(TellorStorage.TellorStorageStruct storage self, uint _requestId, uint _timestamp) internal view returns(bool){ return self.requestDetails[_requestId].inDispute[_timestamp]; } /** * @dev Retreive value from oracle based on requestId/timestamp * @param _requestId being requested * @param _timestamp to retreive data/value from * @return uint value for requestId/timestamp submitted */ function retrieveData(TellorStorage.TellorStorageStruct storage self, uint _requestId, uint _timestamp) internal view returns (uint) { return self.requestDetails[_requestId].finalValues[_timestamp]; } /** * @dev Getter for the total_supply of oracle tokens * @return uint total supply */ function totalSupply(TellorStorage.TellorStorageStruct storage self) internal view returns (uint) { return self.uintVars[keccak256("total_supply")]; } } /** * @title Tellor Oracle System Library * @dev Contains the functions' logic for the Tellor contract where miners can submit the proof of work * along with the value and smart contracts can requestData and tip miners. */ library TellorLibrary{ using SafeMath for uint256; event TipAdded(address indexed _sender,uint indexed _requestId, uint _tip, uint _totalTips); event DataRequested(address indexed _sender, string _query,string _querySymbol,uint _granularity, uint indexed _requestId, uint _totalTips);//Emits upon someone adding value to a pool; msg.sender, amount added, and timestamp incentivized to be mined event NewChallenge(bytes32 _currentChallenge,uint indexed _currentRequestId,uint _difficulty,uint _multiplier,string _query,uint _totalTips); //emits when a new challenge is created (either on mined block or when a new request is pushed forward on waiting system) event NewRequestOnDeck(uint indexed _requestId, string _query, bytes32 _onDeckQueryHash, uint _onDeckTotalTips); //emits when a the payout of another request is higher after adding to the payoutPool or submitting a request event NewValue(uint indexed _requestId, uint _time, uint _value,uint _totalTips,bytes32 _currentChallenge);//Emits upon a successful Mine, indicates the blocktime at point of the mine and the value mined event NonceSubmitted(address indexed _miner, string _nonce, uint indexed _requestId, uint _value,bytes32 _currentChallenge);//Emits upon each mine (5 total) and shows the miner, nonce, and value submitted event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner); event OwnershipProposed(address indexed _previousOwner, address indexed _newOwner); /*Functions*/ /*This is a cheat for demo purposes, will delete upon actual launch*/ /* function theLazyCoon(TellorStorage.TellorStorageStruct storage self,address _address, uint _amount) public { self.uintVars[keccak256("total_supply")] += _amount; TellorTransfer.updateBalanceAtNow(self.balances[_address],_amount); }*/ /** * @dev Add tip to Request value from oracle * @param _requestId being requested to be mined * @param _tip amount the requester is willing to pay to be get on queue. Miners * mine the onDeckQueryHash, or the api with the highest payout pool */ function addTip(TellorStorage.TellorStorageStruct storage self,uint _requestId, uint _tip) public { require(_requestId > 0); //If the tip > 0 transfer the tip to this contract if(_tip > 0){ TellorTransfer.doTransfer(self, msg.sender,address(this),_tip); } //Update the information for the request that should be mined next based on the tip submitted updateOnDeck(self,_requestId,_tip); emit TipAdded(msg.sender,_requestId,_tip,self.requestDetails[_requestId].apiUintVars[keccak256("totalTip")]); } /** * @dev Request to retreive value from oracle based on timestamp. The tip is not required to be * greater than 0 because there are no tokens in circulation for the initial(genesis) request * @param _c_sapi string API being requested be mined * @param _c_symbol is the short string symbol for the api request * @param _granularity is the number of decimals miners should include on the submitted value * @param _tip amount the requester is willing to pay to be get on queue. Miners * mine the onDeckQueryHash, or the api with the highest payout pool */ function requestData(TellorStorage.TellorStorageStruct storage self,string memory _c_sapi,string memory _c_symbol,uint _granularity, uint _tip) public { //Require at least one decimal place require(_granularity > 0); //But no more than 18 decimal places require(_granularity <= 1e18); //If it has been requested before then add the tip to it otherwise create the queryHash for it string memory _sapi = _c_sapi; string memory _symbol = _c_symbol; require(bytes(_sapi).length > 0); require(bytes(_symbol).length < 64); bytes32 _queryHash = keccak256(abi.encodePacked(_sapi,_granularity)); //If this is the first time the API and granularity combination has been requested then create the API and granularity hash //otherwise the tip will be added to the requestId submitted if(self.requestIdByQueryHash[_queryHash] == 0){ self.uintVars[keccak256("requestCount")]++; uint _requestId=self.uintVars[keccak256("requestCount")]; self.requestDetails[_requestId] = TellorStorage.Request({ queryString : _sapi, dataSymbol: _symbol, queryHash: _queryHash, requestTimestamps: new uint[](0) }); self.requestDetails[_requestId].apiUintVars[keccak256("granularity")] = _granularity; self.requestDetails[_requestId].apiUintVars[keccak256("requestQPosition")] = 0; self.requestDetails[_requestId].apiUintVars[keccak256("totalTip")] = 0; self.requestIdByQueryHash[_queryHash] = _requestId; //If the tip > 0 it tranfers the tip to this contract if(_tip > 0){ TellorTransfer.doTransfer(self, msg.sender,address(this),_tip); } updateOnDeck(self,_requestId,_tip); emit DataRequested(msg.sender,self.requestDetails[_requestId].queryString,self.requestDetails[_requestId].dataSymbol,_granularity,_requestId,_tip); } //Add tip to existing request id since this is not the first time the api and granularity have been requested else{ addTip(self,self.requestIdByQueryHash[_queryHash],_tip); } } /** * @dev This fucntion is called by submitMiningSolution and adjusts the difficulty, sorts and stores the first * 5 values received, pays the miners, the dev share and assigns a new challenge * @param _nonce or solution for the PoW for the requestId * @param _requestId for the current request being mined */ function newBlock(TellorStorage.TellorStorageStruct storage self,string memory _nonce, uint _requestId) internal{ TellorStorage.Request storage _request = self.requestDetails[_requestId]; // If the difference between the timeTarget and how long it takes to solve the challenge this updates the challenge //difficulty up or donw by the difference between the target time and how long it took to solve the prevous challenge //otherwise it sets it to 1 int _newDiff = int(self.uintVars[keccak256("difficulty")]) + int(self.uintVars[keccak256("difficulty")]) * (int(self.uintVars[keccak256("timeTarget")]) - int(now - self.uintVars[keccak256("timeOfLastNewValue")]))/100; if(_newDiff <= 0){ self.uintVars[keccak256("difficulty")] = 1; } else{ self.uintVars[keccak256("difficulty")] = uint(_newDiff); } //Sets time of value submission rounded to 1 minute uint _timeOfLastNewValue = now - (now % 1 minutes); self.uintVars[keccak256("timeOfLastNewValue")] = _timeOfLastNewValue; //The sorting algorithm that sorts the values of the first five values that come in TellorStorage.Details[5] memory a = self.currentMiners; uint i; for (i = 1;i <5;i++){ uint temp = a[i].value; address temp2 = a[i].miner; uint j = i; while(j > 0 && temp < a[j-1].value){ a[j].value = a[j-1].value; a[j].miner = a[j-1].miner; j--; } if(j<i){ a[j].value = temp; a[j].miner= temp2; } } //Pay the miners for (i = 0;i <5;i++){ TellorTransfer.doTransfer(self,address(this),a[i].miner,5e18 + self.uintVars[keccak256("currentTotalTips")]/5); } emit NewValue(_requestId,_timeOfLastNewValue,a[2].value,self.uintVars[keccak256("currentTotalTips")] - self.uintVars[keccak256("currentTotalTips")] % 5,self.currentChallenge); //update the total supply self.uintVars[keccak256("total_supply")] += 275e17; //pay the dev-share TellorTransfer.doTransfer(self, address(this),self.addressVars[keccak256("_owner")],25e17);//The ten there is the devshare //Save the official(finalValue), timestamp of it, 5 miners and their submitted values for it, and its block number _request.finalValues[_timeOfLastNewValue] = a[2].value; _request.requestTimestamps.push(_timeOfLastNewValue); //these are miners by timestamp _request.minersByValue[_timeOfLastNewValue] = [a[0].miner,a[1].miner,a[2].miner,a[3].miner,a[4].miner]; _request.valuesByTimestamp[_timeOfLastNewValue] = [a[0].value,a[1].value,a[2].value,a[3].value,a[4].value]; _request.minedBlockNum[_timeOfLastNewValue] = block.number; //map the timeOfLastValue to the requestId that was just mined self.requestIdByTimestamp[_timeOfLastNewValue] = _requestId; //add timeOfLastValue to the newValueTimestamps array self.newValueTimestamps.push(_timeOfLastNewValue); //re-start the count for the slot progress to zero before the new request mining starts self.uintVars[keccak256("slotProgress")] = 0; uint _topId = TellorGettersLibrary.getTopRequestID(self); self.uintVars[keccak256("currentRequestId")] = _topId; //if the currentRequestId is not zero(currentRequestId exists/something is being mined) select the requestId with the hightest payout //else wait for a new tip to mine if(_topId > 0){ //Update the current request to be mined to the requestID with the highest payout self.uintVars[keccak256("currentTotalTips")] = self.requestDetails[_topId].apiUintVars[keccak256("totalTip")]; //Remove the currentRequestId/onDeckRequestId from the requestQ array containing the rest of the 50 requests self.requestQ[self.requestDetails[_topId].apiUintVars[keccak256("requestQPosition")]] = 0; //unmap the currentRequestId/onDeckRequestId from the requestIdByRequestQIndex self.requestIdByRequestQIndex[self.requestDetails[_topId].apiUintVars[keccak256("requestQPosition")]] = 0; //Remove the requestQposition for the currentRequestId/onDeckRequestId since it will be mined next self.requestDetails[_topId].apiUintVars[keccak256("requestQPosition")] = 0; //Reset the requestId TotalTip to 0 for the currentRequestId/onDeckRequestId since it will be mined next //and the tip is going to the current timestamp miners. The tip for the API needs to be reset to zero self.requestDetails[_topId].apiUintVars[keccak256("totalTip")] = 0; //gets the max tip in the in the requestQ[51] array and its index within the array?? uint newRequestId = TellorGettersLibrary.getTopRequestID(self); //Issue the the next challenge self.currentChallenge = keccak256(abi.encodePacked(_nonce,self.currentChallenge, blockhash(block.number - 1))); // Save hash for next proof emit NewChallenge(self.currentChallenge,_topId,self.uintVars[keccak256("difficulty")],self.requestDetails[_topId].apiUintVars[keccak256("granularity")],self.requestDetails[_topId].queryString,self.uintVars[keccak256("currentTotalTips")]); emit NewRequestOnDeck(newRequestId,self.requestDetails[newRequestId].queryString,self.requestDetails[newRequestId].queryHash, self.requestDetails[newRequestId].apiUintVars[keccak256("totalTip")]); } else{ self.uintVars[keccak256("currentTotalTips")] = 0; self.currentChallenge = ""; } } /** * @dev Proof of work is called by the miner when they submit the solution (proof of work and value) * @param _nonce uint submitted by miner * @param _requestId the apiId being mined * @param _value of api query */ function submitMiningSolution(TellorStorage.TellorStorageStruct storage self,string memory _nonce, uint _requestId, uint _value) public{ //requre miner is staked require(self.stakerDetails[msg.sender].currentStatus == 1); //Check the miner is submitting the pow for the current request Id require(_requestId == self.uintVars[keccak256("currentRequestId")]); //Saving the challenge information as unique by using the msg.sender require(uint(sha256(abi.encodePacked(ripemd160(abi.encodePacked(keccak256(abi.encodePacked(self.currentChallenge,msg.sender,_nonce))))))) % self.uintVars[keccak256("difficulty")] == 0); //Make sure the miner does not submit a value more than once require(self.minersByChallenge[self.currentChallenge][msg.sender] == false); //Save the miner and value received self.currentMiners[self.uintVars[keccak256("slotProgress")]].value = _value; self.currentMiners[self.uintVars[keccak256("slotProgress")]].miner = msg.sender; //Add to the count how many values have been submitted, since only 5 are taken per request self.uintVars[keccak256("slotProgress")]++; //Update the miner status to true once they submit a value so they don't submit more than once self.minersByChallenge[self.currentChallenge][msg.sender] = true; emit NonceSubmitted(msg.sender,_nonce,_requestId,_value,self.currentChallenge); //If 5 values have been received, adjust the difficulty otherwise sort the values until 5 are received if(self.uintVars[keccak256("slotProgress")] == 5) { newBlock(self,_nonce,_requestId); } } /** * @dev Allows the current owner to propose transfer control of the contract to a * newOwner and the ownership is pending until the new owner calls the claimOwnership * function * @param _pendingOwner The address to transfer ownership to. */ function proposeOwnership(TellorStorage.TellorStorageStruct storage self,address payable _pendingOwner) internal { require(msg.sender == self.addressVars[keccak256("_owner")]); emit OwnershipProposed(self.addressVars[keccak256("_owner")], _pendingOwner); self.addressVars[keccak256("pending_owner")] = _pendingOwner; } /** * @dev Allows the new owner to claim control of the contract */ function claimOwnership(TellorStorage.TellorStorageStruct storage self) internal { require(msg.sender == self.addressVars[keccak256("pending_owner")]); emit OwnershipTransferred(self.addressVars[keccak256("_owner")], self.addressVars[keccak256("pending_owner")]); self.addressVars[keccak256("_owner")] = self.addressVars[keccak256("pending_owner")]; } /** * @dev This function updates APIonQ and the requestQ when requestData or addTip are ran * @param _requestId being requested * @param _tip is the tip to add */ function updateOnDeck(TellorStorage.TellorStorageStruct storage self,uint _requestId, uint _tip) internal { TellorStorage.Request storage _request = self.requestDetails[_requestId]; uint onDeckRequestId = TellorGettersLibrary.getTopRequestID(self); //If the tip >0 update the tip for the requestId if (_tip > 0){ _request.apiUintVars[keccak256("totalTip")] = _request.apiUintVars[keccak256("totalTip")].add(_tip); } //Set _payout for the submitted request uint _payout = _request.apiUintVars[keccak256("totalTip")]; //If there is no current request being mined //then set the currentRequestId to the requestid of the requestData or addtip requestId submitted, // the totalTips to the payout/tip submitted, and issue a new mining challenge if(self.uintVars[keccak256("currentRequestId")] == 0){ _request.apiUintVars[keccak256("totalTip")] = 0; self.uintVars[keccak256("currentRequestId")] = _requestId; self.uintVars[keccak256("currentTotalTips")] = _payout; self.currentChallenge = keccak256(abi.encodePacked(_payout, self.currentChallenge, blockhash(block.number - 1))); // Save hash for next proof emit NewChallenge(self.currentChallenge,self.uintVars[keccak256("currentRequestId")],self.uintVars[keccak256("difficulty")],self.requestDetails[self.uintVars[keccak256("currentRequestId")]].apiUintVars[keccak256("granularity")],self.requestDetails[self.uintVars[keccak256("currentRequestId")]].queryString,self.uintVars[keccak256("currentTotalTips")]); } else{ //If there is no OnDeckRequestId //then replace/add the requestId to be the OnDeckRequestId, queryHash and OnDeckTotalTips(current highest payout, aside from what //is being currently mined) if (_payout > self.requestDetails[onDeckRequestId].apiUintVars[keccak256("totalTip")] || (onDeckRequestId == 0)) { //let everyone know the next on queue has been replaced emit NewRequestOnDeck(_requestId,_request.queryString,_request.queryHash ,_payout); } //if the request is not part of the requestQ[51] array //then add to the requestQ[51] only if the _payout/tip is greater than the minimum(tip) in the requestQ[51] array if(_request.apiUintVars[keccak256("requestQPosition")] == 0){ uint _min; uint _index; (_min,_index) = Utilities.getMin(self.requestQ); //we have to zero out the oldOne //if the _payout is greater than the current minimum payout in the requestQ[51] or if the minimum is zero //then add it to the requestQ array aand map its index information to the requestId and the apiUintvars if(_payout > _min || _min == 0){ self.requestQ[_index] = _payout; self.requestDetails[self.requestIdByRequestQIndex[_index]].apiUintVars[keccak256("requestQPosition")] = 0; self.requestIdByRequestQIndex[_index] = _requestId; _request.apiUintVars[keccak256("requestQPosition")] = _index; } } //else if the requestid is part of the requestQ[51] then update the tip for it else if (_tip > 0){ self.requestQ[_request.apiUintVars[keccak256("requestQPosition")]] += _tip; } } } } /** * @title Tellor Oracle System * @dev Oracle contract where miners can submit the proof of work along with the value. * The logic for this contract is in TellorLibrary.sol, TellorDispute.sol, TellorStake.sol, * and TellorTransfer.sol */ contract Tellor{ using SafeMath for uint256; using TellorDispute for TellorStorage.TellorStorageStruct; using TellorLibrary for TellorStorage.TellorStorageStruct; using TellorStake for TellorStorage.TellorStorageStruct; using TellorTransfer for TellorStorage.TellorStorageStruct; TellorStorage.TellorStorageStruct tellor; /*Functions*/ /*This is a cheat for demo purposes, will delete upon actual launch*/ /* function theLazyCoon(address _address, uint _amount) public { tellor.theLazyCoon(_address,_amount); }*/ /** * @dev Helps initialize a dispute by assigning it a disputeId * when a miner returns a false on the validate array(in Tellor.ProofOfWork) it sends the * invalidated value information to POS voting * @param _requestId being disputed * @param _timestamp being disputed * @param _minerIndex the index of the miner that submitted the value being disputed. Since each official value * requires 5 miners to submit a value. */ function beginDispute(uint _requestId, uint _timestamp,uint _minerIndex) external { tellor.beginDispute(_requestId,_timestamp,_minerIndex); } /** * @dev Allows token holders to vote * @param _disputeId is the dispute id * @param _supportsDispute is the vote (true=the dispute has basis false = vote against dispute) */ function vote(uint _disputeId, bool _supportsDispute) external { tellor.vote(_disputeId,_supportsDispute); } /** * @dev tallies the votes. * @param _disputeId is the dispute id */ function tallyVotes(uint _disputeId) external { tellor.tallyVotes(_disputeId); } /** * @dev Allows for a fork to be proposed * @param _propNewTellorAddress address for new proposed Tellor */ function proposeFork(address _propNewTellorAddress) external { tellor.proposeFork(_propNewTellorAddress); } /** * @dev Add tip to Request value from oracle * @param _requestId being requested to be mined * @param _tip amount the requester is willing to pay to be get on queue. Miners * mine the onDeckQueryHash, or the api with the highest payout pool */ function addTip(uint _requestId, uint _tip) external { tellor.addTip(_requestId,_tip); } /** * @dev Request to retreive value from oracle based on timestamp. The tip is not required to be * greater than 0 because there are no tokens in circulation for the initial(genesis) request * @param _c_sapi string API being requested be mined * @param _c_symbol is the short string symbol for the api request * @param _granularity is the number of decimals miners should include on the submitted value * @param _tip amount the requester is willing to pay to be get on queue. Miners * mine the onDeckQueryHash, or the api with the highest payout pool */ function requestData(string calldata _c_sapi,string calldata _c_symbol,uint _granularity, uint _tip) external { tellor.requestData(_c_sapi,_c_symbol,_granularity,_tip); } /** * @dev Proof of work is called by the miner when they submit the solution (proof of work and value) * @param _nonce uint submitted by miner * @param _requestId the apiId being mined * @param _value of api query */ function submitMiningSolution(string calldata _nonce, uint _requestId, uint _value) external{ tellor.submitMiningSolution(_nonce,_requestId,_value); } /** * @dev Allows the current owner to propose transfer control of the contract to a * newOwner and the ownership is pending until the new owner calls the claimOwnership * function * @param _pendingOwner The address to transfer ownership to. */ function proposeOwnership(address payable _pendingOwner) external { tellor.proposeOwnership(_pendingOwner); } /** * @dev Allows the new owner to claim control of the contract */ function claimOwnership() external { tellor.claimOwnership(); } /** * @dev This function allows miners to deposit their stake. */ function depositStake() external { tellor.depositStake(); } /** * @dev This function allows stakers to request to withdraw their stake (no longer stake) * once they lock for withdraw(stakes.currentStatus = 2) they are locked for 7 days before they * can withdraw the stake */ function requestStakingWithdraw() external { tellor.requestStakingWithdraw(); } /** * @dev This function allows users to withdraw their stake after a 7 day waiting period from request */ function withdrawStake() external { tellor.withdrawStake(); } /** * @dev This function approves a _spender an _amount of tokens to use * @param _spender address * @param _amount amount the spender is being approved for * @return true if spender appproved successfully */ function approve(address _spender, uint _amount) external returns (bool) { return tellor.approve(_spender,_amount); } /** * @dev Allows for a transfer of tokens to _to * @param _to The address to send tokens to * @param _amount The amount of tokens to send * @return true if transfer is successful */ function transfer(address _to, uint256 _amount) external returns (bool) { return tellor.transfer(_to,_amount); } /** * @notice Send _amount tokens to _to from _from on the condition it * is approved by _from * @param _from The address holding the tokens being transferred * @param _to The address of the recipient * @param _amount The amount of tokens to be transferred * @return True if the transfer was successful */ function transferFrom(address _from, address _to, uint256 _amount) external returns (bool) { return tellor.transferFrom(_from,_to,_amount); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"depositStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_propNewTellorAddress","type":"address"}],"name":"proposeFork","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"requestStakingWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_c_sapi","type":"string"},{"name":"_c_symbol","type":"string"},{"name":"_granularity","type":"uint256"},{"name":"_tip","type":"uint256"}],"name":"requestData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"tallyVotes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nonce","type":"string"},{"name":"_requestId","type":"uint256"},{"name":"_value","type":"uint256"}],"name":"submitMiningSolution","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_pendingOwner","type":"address"}],"name":"proposeOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"uint256"},{"name":"_tip","type":"uint256"}],"name":"addTip","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"uint256"},{"name":"_timestamp","type":"uint256"},{"name":"_minerIndex","type":"uint256"}],"name":"beginDispute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_supportsDispute","type":"bool"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061127f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80634e71e0c8116100975780638581af19116100665780638581af1914610461578063a9059cbb146104a3578063bed9d86114610509578063c9d27afe14610513576100f5565b80634e71e0c81461034e57806368c180d514610358578063710bf322146103e5578063752d49a114610429576100f5565b806326b7d9f6116100d357806326b7d9f6146101f057806328449c3a146102345780633fff28161461023e5780634d318b0e14610320576100f5565b8063095ea7b3146100fa5780630d2d76a21461016057806323b872dd1461016a575b600080fd5b6101466004803603604081101561011057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061054d565b604051808215151515815260200191505060405180910390f35b61016861061f565b005b6101d66004803603606081101561018057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061068b565b604051808215151515815260200191505060405180910390f35b6102326004803603602081101561020657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610792565b005b61023c610833565b005b61031e6004803603608081101561025457600080fd5b810190808035906020019064010000000081111561027157600080fd5b82018360208201111561028357600080fd5b803590602001918460018302840111640100000000831117156102a557600080fd5b9091929391929390803590602001906401000000008111156102c657600080fd5b8201836020820111156102d857600080fd5b803590602001918460018302840111640100000000831117156102fa57600080fd5b9091929391929390803590602001909291908035906020019092919050505061089f565b005b61034c6004803603602081101561033657600080fd5b8101908080359060200190929190505050610989565b005b6103566109fe565b005b6103e36004803603606081101561036e57600080fd5b810190808035906020019064010000000081111561038b57600080fd5b82018360208201111561039d57600080fd5b803590602001918460018302840111640100000000831117156103bf57600080fd5b90919293919293908035906020019092919080359060200190929190505050610a0a565b005b610427600480360360208110156103fb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610abe565b005b61045f6004803603604081101561043f57600080fd5b810190808035906020019092919080359060200190929190505050610ad5565b005b6104a16004803603606081101561047757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610b53565b005b6104ef600480360360408110156104b957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bda565b604051808215151515815260200191505060405180910390f35b610511610cac565b005b61054b6004803603604081101561052957600080fd5b8101908080359060200190929190803515159060200190929190505050610d18565b005b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63850dcc32909185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b1580156105dc57600080fd5b505af41580156105f0573d6000803e3d6000fd5b505050506040513d602081101561060657600080fd5b8101908080519060200190929190505050905092915050565b600073114d0b96a13bdd0778908b9a02a160647599524963820a2d6690916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561067157600080fd5b505af4158015610685573d6000803e3d6000fd5b50505050565b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63ca50189990918686866040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060206040518083038186803b15801561074e57600080fd5b505af4158015610762573d6000803e3d6000fd5b505050506040513d602081101561077857600080fd5b810190808051906020019092919050505090509392505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63694bf49f9091836040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060006040518083038186803b15801561081857600080fd5b505af415801561082c573d6000803e3d6000fd5b5050505050565b600073114d0b96a13bdd0778908b9a02a160647599524963c9cf5e4c90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561088557600080fd5b505af4158015610899573d6000803e3d6000fd5b50505050565b6000736a6a43dd58996ef83f4171b33e0108808130760f6385997bf690918888888888886040518863ffffffff1660e01b81526004018088815260200180602001806020018581526020018481526020018381038352898982818152602001925080828437600081840152601f19601f8201169050808301925050508381038252878782818152602001925080828437600081840152601f19601f820116905080830192505050995050505050505050505060006040518083038186803b15801561096957600080fd5b505af415801561097d573d6000803e3d6000fd5b50505050505050505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63def6fac79091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156109e357600080fd5b505af41580156109f7573d6000803e3d6000fd5b5050505050565b610a086000610d9a565b565b6000736a6a43dd58996ef83f4171b33e0108808130760f63a098b5b49091868686866040518663ffffffff1660e01b815260040180868152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060006040518083038186803b158015610aa057600080fd5b505af4158015610ab4573d6000803e3d6000fd5b5050505050505050565b610ad281600061106090919063ffffffff16565b50565b6000736a6a43dd58996ef83f4171b33e0108808130760f6302e8f21b909184846040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060006040518083038186803b158015610b3757600080fd5b505af4158015610b4b573d6000803e3d6000fd5b505050505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63ca9a4ea590918585856040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060006040518083038186803b158015610bbd57600080fd5b505af4158015610bd1573d6000803e3d6000fd5b50505050505050565b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63c84b96f5909185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b158015610c6957600080fd5b505af4158015610c7d573d6000803e3d6000fd5b505050506040513d6020811015610c9357600080fd5b8101908080519060200190929190505050905092915050565b600073114d0b96a13bdd0778908b9a02a16064759952496344bacc4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015610cfe57600080fd5b505af4158015610d12573d6000803e3d6000fd5b50505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f632da0706e909184846040518463ffffffff1660e01b81526004018084815260200183815260200182151515158152602001935050505060006040518083038186803b158015610d7e57600080fd5b505af4158015610d92573d6000803e3d6000fd5b505050505050565b80603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e3c57600080fd5b80603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b81603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461110257600080fd5b8073ffffffffffffffffffffffffffffffffffffffff1682603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb51454ce8c7f26becd312a46c4815553887f2ec876a0b8dc813b87f62edf6f8060405160405180910390a38082603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea165627a7a72305820b7e578b52c2aaf1438f0ab1285c0615ec8a231344b83f12a49f9879b1d0c7db60029
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80634e71e0c8116100975780638581af19116100665780638581af1914610461578063a9059cbb146104a3578063bed9d86114610509578063c9d27afe14610513576100f5565b80634e71e0c81461034e57806368c180d514610358578063710bf322146103e5578063752d49a114610429576100f5565b806326b7d9f6116100d357806326b7d9f6146101f057806328449c3a146102345780633fff28161461023e5780634d318b0e14610320576100f5565b8063095ea7b3146100fa5780630d2d76a21461016057806323b872dd1461016a575b600080fd5b6101466004803603604081101561011057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061054d565b604051808215151515815260200191505060405180910390f35b61016861061f565b005b6101d66004803603606081101561018057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061068b565b604051808215151515815260200191505060405180910390f35b6102326004803603602081101561020657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610792565b005b61023c610833565b005b61031e6004803603608081101561025457600080fd5b810190808035906020019064010000000081111561027157600080fd5b82018360208201111561028357600080fd5b803590602001918460018302840111640100000000831117156102a557600080fd5b9091929391929390803590602001906401000000008111156102c657600080fd5b8201836020820111156102d857600080fd5b803590602001918460018302840111640100000000831117156102fa57600080fd5b9091929391929390803590602001909291908035906020019092919050505061089f565b005b61034c6004803603602081101561033657600080fd5b8101908080359060200190929190505050610989565b005b6103566109fe565b005b6103e36004803603606081101561036e57600080fd5b810190808035906020019064010000000081111561038b57600080fd5b82018360208201111561039d57600080fd5b803590602001918460018302840111640100000000831117156103bf57600080fd5b90919293919293908035906020019092919080359060200190929190505050610a0a565b005b610427600480360360208110156103fb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610abe565b005b61045f6004803603604081101561043f57600080fd5b810190808035906020019092919080359060200190929190505050610ad5565b005b6104a16004803603606081101561047757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610b53565b005b6104ef600480360360408110156104b957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bda565b604051808215151515815260200191505060405180910390f35b610511610cac565b005b61054b6004803603604081101561052957600080fd5b8101908080359060200190929190803515159060200190929190505050610d18565b005b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63850dcc32909185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b1580156105dc57600080fd5b505af41580156105f0573d6000803e3d6000fd5b505050506040513d602081101561060657600080fd5b8101908080519060200190929190505050905092915050565b600073114d0b96a13bdd0778908b9a02a160647599524963820a2d6690916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561067157600080fd5b505af4158015610685573d6000803e3d6000fd5b50505050565b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63ca50189990918686866040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060206040518083038186803b15801561074e57600080fd5b505af4158015610762573d6000803e3d6000fd5b505050506040513d602081101561077857600080fd5b810190808051906020019092919050505090509392505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63694bf49f9091836040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060006040518083038186803b15801561081857600080fd5b505af415801561082c573d6000803e3d6000fd5b5050505050565b600073114d0b96a13bdd0778908b9a02a160647599524963c9cf5e4c90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561088557600080fd5b505af4158015610899573d6000803e3d6000fd5b50505050565b6000736a6a43dd58996ef83f4171b33e0108808130760f6385997bf690918888888888886040518863ffffffff1660e01b81526004018088815260200180602001806020018581526020018481526020018381038352898982818152602001925080828437600081840152601f19601f8201169050808301925050508381038252878782818152602001925080828437600081840152601f19601f820116905080830192505050995050505050505050505060006040518083038186803b15801561096957600080fd5b505af415801561097d573d6000803e3d6000fd5b50505050505050505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63def6fac79091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156109e357600080fd5b505af41580156109f7573d6000803e3d6000fd5b5050505050565b610a086000610d9a565b565b6000736a6a43dd58996ef83f4171b33e0108808130760f63a098b5b49091868686866040518663ffffffff1660e01b815260040180868152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060006040518083038186803b158015610aa057600080fd5b505af4158015610ab4573d6000803e3d6000fd5b5050505050505050565b610ad281600061106090919063ffffffff16565b50565b6000736a6a43dd58996ef83f4171b33e0108808130760f6302e8f21b909184846040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060006040518083038186803b158015610b3757600080fd5b505af4158015610b4b573d6000803e3d6000fd5b505050505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f63ca9a4ea590918585856040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060006040518083038186803b158015610bbd57600080fd5b505af4158015610bd1573d6000803e3d6000fd5b50505050505050565b60008073aaed2224d17326c9b710925f075dce1e2bbc77df63c84b96f5909185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b158015610c6957600080fd5b505af4158015610c7d573d6000803e3d6000fd5b505050506040513d6020811015610c9357600080fd5b8101908080519060200190929190505050905092915050565b600073114d0b96a13bdd0778908b9a02a16064759952496344bacc4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015610cfe57600080fd5b505af4158015610d12573d6000803e3d6000fd5b50505050565b600073f24fade75e40db2cb80dfac9600cecf34728590f632da0706e909184846040518463ffffffff1660e01b81526004018084815260200183815260200182151515158152602001935050505060006040518083038186803b158015610d7e57600080fd5b505af4158015610d92573d6000803e3d6000fd5b505050505050565b80603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e3c57600080fd5b80603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b81603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461110257600080fd5b8073ffffffffffffffffffffffffffffffffffffffff1682603f01600060405180807f5f6f776e6572000000000000000000000000000000000000000000000000000081525060060190506040518091039020815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb51454ce8c7f26becd312a46c4815553887f2ec876a0b8dc813b87f62edf6f8060405160405180910390a38082603f01600060405180807f70656e64696e675f6f776e657200000000000000000000000000000000000000815250600d0190506040518091039020815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea165627a7a72305820b7e578b52c2aaf1438f0ab1285c0615ec8a231344b83f12a49f9879b1d0c7db60029
Libraries Used
TellorTransfer : 0xaaed2224d17326c9b710925f075dce1e2bbc77dfUnverifiedTellorDispute : 0xf24fade75e40db2cb80dfac9600cecf34728590fUnverifiedTellorStake : 0x114d0b96a13bdd0778908b9a02a1606475995249UnverifiedTellorLibrary : 0x6a6a43dd58996ef83f4171b33e0108808130760fUnverified
Deployed Bytecode Sourcemap
73603:6160:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73603:6160:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78767:131;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;78767:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;77891:73;;;:::i;:::-;;79603:155;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;79603:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;75493:121;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;75493:121:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;78217:93;;;:::i;:::-;;76614:184;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;76614:184:0;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;76614:184:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;76614:184:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;76614:184:0;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;76614:184:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;76614:184:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;76614:184:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;75259:94;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;75259:94:0;;;;;;;;;;;;;;;;;:::i;:::-;;77723:77;;;:::i;:::-;;77056:164;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;77056:164:0;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;77056:164:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;77056:164:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;77056:164:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;77507:123;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;77507:123:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;75900:102;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;75900:102:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;74669:155;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;74669:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;79121:126;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;79121:126:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;78443:75;;;:::i;:::-;;75036:122;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;75036:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;78767:131;78834:4;78858:6;:14;;;;78873:8;78882:7;78858:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;78858:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;78858:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;78858:32:0;;;;;;;;;;;;;;;;78851:39;;78767:131;;;;:::o;77891:73::-;77935:6;:19;;;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;77935:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77935:21:0;;;;77891:73::o;79603:155::-;79688:4;79712:6;:19;;;;79732:5;79738:3;79742:7;79712:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79712:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79712:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;79712:38:0;;;;;;;;;;;;;;;;79705:45;;79603:155;;;;;:::o;75493:121::-;75565:6;:18;;;;75584:21;75565:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75565:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75565:41:0;;;;75493:121;:::o;78217:93::-;78271:6;:29;;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;78271:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;78271:31:0;;;;78217:93::o;76614:184::-;76735:6;:18;;;;76754:7;;76762:9;;76772:12;76785:4;76735:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;76735:55:0;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;76735:55:0;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;76735:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76735:55:0;;;;76614:184;;;;;;:::o;75259:94::-;75316:6;:17;;;;75334:10;75316:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75316:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75316:29:0;;;;75259:94;:::o;77723:77::-;77769:23;:6;:21;:23::i;:::-;77723:77::o;77056:164::-;77159:6;:27;;;;77187:6;;77194:10;77205:6;77159:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;77159:53:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;77159:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77159:53:0;;;;77056:164;;;;:::o;77507:123::-;77584:38;77608:13;77584:6;:23;;:38;;;;:::i;:::-;77507:123;:::o;75900:102::-;75964:6;:13;;;;75978:10;75989:4;75964:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75964:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75964:30:0;;;;75900:102;;:::o;74669:155::-;74762:6;:19;;;;74782:10;74793;74804:11;74762:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;74762:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;74762:54:0;;;;74669:155;;;:::o;79121:126::-;79187:4;79211:6;:15;;;;79227:3;79231:7;79211:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79211:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79211:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;79211:28:0;;;;;;;;;;;;;;;;79204:35;;79121:126;;;;:::o;78443:75::-;78488:6;:20;;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;78488:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;78488:22:0;;;;78443:75::o;75036:122::-;75110:6;:11;;;;75122:10;75133:16;75110:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75110:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75110:40:0;;;;75036:122;;:::o;69163:383::-;69277:4;:16;;:44;69294:26;;;;;;;;;;;;;;;;;;;69277:44;;;;;;;;;;;;;;;;;;;;;69263:58;;:10;:58;;;69255:67;;;;;;69398:4;:16;;:44;69415:26;;;;;;;;;;;;;;;;;;;69398:44;;;;;;;;;;;;;;;;;;;;;69338:105;;69359:4;:16;;:37;69376:19;;;;;;;;;;;;;;;;;;;69359:37;;;;;;;;;;;;;;;;;;;;;69338:105;;;;;;;;;;;;69494:4;:16;;:44;69511:26;;;;;;;;;;;;;;;;;;;69494:44;;;;;;;;;;;;;;;;;;;;;69454:4;:16;;:37;69471:19;;;;;;;;;;;;;;;;;;;69454:37;;;;;;;;;;;;:84;;;;;;;;;;;;;;;;;;69163:383;:::o;68720:350::-;68866:4;:16;;:37;68883:19;;;;;;;;;;;;;;;;;;;68866:37;;;;;;;;;;;;;;;;;;;;;68852:51;;:10;:51;;;68844:60;;;;;;68977:13;68920:71;;68938:4;:16;;:37;68955:19;;;;;;;;;;;;;;;;;;;68938:37;;;;;;;;;;;;;;;;;;;;;68920:71;;;;;;;;;;;;69049:13;69002:4;:16;;:44;69019:26;;;;;;;;;;;;;;;;;;;69002:44;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;68720:350;;:::o
Swarm Source
bzzr://b7e578b52c2aaf1438f0ab1285c0615ec8a231344b83f12a49f9879b1d0c7db6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 25 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.