One of the earliest Oraclize-powered smart contracts on Ethereum — a YouTube views sponsorship bounty deployed January 25, 2016.
Key Facts
Description
The YoutubeViews contract is one of the earliest known Oraclize integrations on Ethereum mainnet, deployed on January 25, 2016 (block 904,395) during the Frontier era.
The contract implements a YouTube views sponsorship bounty: sponsors deposit ETH, and the contract uses the Oraclize oracle service to fetch the view count of a specified YouTube video via XPath query. If the video reaches a set threshold by a deadline (the expiry date), the contract owner receives the accumulated funds minus a 25% sponsor refund. If the threshold is not met, the sponsors receive 25% of their deposits back.
The Oraclize XPath query used: html(https://www.youtube.com/watch?v=VIDEO_ID).xpath(//*[contains(@class, "watch-view-count")]/text())
Oraclize (later rebranded as Provable) was one of the first oracle infrastructure projects for Ethereum, allowing smart contracts to make authenticated HTTP requests to real-world data sources. This contract represents an early experiment combining decentralized finance mechanics with social media metrics.
The contract holds 33.5 ETH, locked since January 2016. With Oraclize's infrastructure no longer operational and no admin drain function in the contract, these funds are permanently inaccessible.
Source Verified
Source fully reconstructed. All 13 function selectors resolved. Contract: YoutubeViews is usingOraclize, Oraclize API commit f352e3ac (Jan 2016), compiler soljson v0.2.0 nightly with optimizer ON. Compiled output matches on-chain runtime (4127 bytes) with one exception: parseInt(1-arg) return epilogue (7 bytes) placed at offset 0x099e on-chain vs 0x0d05 in compiled — a code generation scheduling artifact in the JS compiler tag queue. All function implementations, dispatch table, and jump targets are otherwise identical.
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Source CodeShow source code (Solidity)
// YoutubeViews.sol
// Compiler: soljson-v0.2.0 nightly (Jan 18-28 2016), optimizer ON
// Oraclize API: commit f352e3ac (Jan 2016, 3-network variant, strConcat-first ordering)
import "oraclizeAPI.sol";
contract YoutubeViews is usingOraclize {
uint public viewsCount;
string public videoID;
address public owner;
uint public expiryDate;
uint public threshold;
mapping (address => uint) public sponsors;
address[] public sponsorsList;
function YoutubeViews() {
owner = msg.sender;
oraclize_setNetwork(networkID_consensys);
}
function setVideoID(string _videoID, uint _threshold) {
if ((msg.sender != owner)||(bytes(videoID).length != 0)||(bytes(_videoID).length == 0)) throw;
videoID = _videoID;
uint _expiryDate = now+1*day;
expiryDate = _expiryDate;
threshold = _threshold;
sendQuery(_expiryDate);
}
function() { sponsorDeposit(); }
function sponsorDeposit() public {
if ((msg.value == 0)||(bytes(videoID).length == 0)) throw;
if (sponsors[msg.sender] == 0) sponsorsList[sponsorsList.length++] = msg.sender;
sponsors[msg.sender] += msg.value;
if ((now >= expiryDate)&&(viewsCount > 0)) processWithdrawals();
}
function __callback(bytes32 myid, string result) {
if (msg.sender != oraclize_cbAddress()) throw;
viewsCount = parseInt(result);
processWithdrawals();
}
function processWithdrawals() internal {
if (viewsCount < threshold) {
address _sponsor;
for (uint i=0; i<sponsorsList.length; i++){
_sponsor = sponsorsList[i];
_sponsor.send(sponsors[_sponsor]/4);
}
}
owner.send(this.balance);
}
function sendQuery(uint delay) internal {
string memory videoURL = strConcat("html(https://www.youtube.com/watch?v=", videoID, ").xpath(//*[contains(@class, \"watch-view-count\")]/text())");
oraclize_query(delay, "URL", videoURL);
}
function forceCheck() public {
if ((msg.sender != owner)||(now < expiryDate+60*60)) throw;
sendQuery(expiryDate);
}
}