The first draft of the EarlyLottery commit-reveal lottery, deployed on 8 August 2015 a few hours before its rewrite.
Historical Significance
The earliest of the commit-reveal lottery drafts by 0xfd2605a2bf58fdbb90db1da55df61628b47f9e8c, deployed on 8 August 2015 and replaced by a shorter rewrite the same evening. Play runs on an 88 block cycle. buyTicket(bytes32) accepts a hash commitment during the first 40 blocks of the cycle and credits the ether sent with it. submitSecret(uint64) reveals the preimage between blocks 48 and 68. payout() fires once block.number modulo 88 passes 68 and at least 68 blocks have elapsed since the last draw, and sends the pot minus 25000 times tx.gasprice. What sets this draft apart is random(): it xors the revealed secrets together and then folds the result down toward the ticket count by repeated division by 65536, with two separate modulo escapes on the way out. The rewrite deployed hours later throws that away for a single modulo. Both drafts share the same fatal reveal bug, an out of bounds write to secrets[secrets.length] that always throws. Source recovered by exact bytecode match: solc v0.1.1+commit.6ff4cd6 with the optimizer on reproduces all 1096 bytes of the creation transaction.
Context
Deployed 8 August 2015, the second day of the Ethereum Frontier network.
Key Facts
Description
The earliest of the commit-reveal lottery drafts by 0xfd2605a2bf58fdbb90db1da55df61628b47f9e8c, deployed on 8 August 2015 and replaced by a shorter rewrite the same evening. Play runs on an 88 block cycle. buyTicket(bytes32) accepts a hash commitment during the first 40 blocks of the cycle and credits the ether sent with it. submitSecret(uint64) reveals the preimage between blocks 48 and 68. payout() fires once block.number modulo 88 passes 68 and at least 68 blocks have elapsed since the last draw, and sends the pot minus 25000 times tx.gasprice. What sets this draft apart is random(): it xors the revealed secrets together and then folds the result down toward the ticket count by repeated division by 65536, with two separate modulo escapes on the way out. The rewrite deployed hours later throws that away for a single modulo. Both drafts share the same fatal reveal bug, an out of bounds write to secrets[secrets.length] that always throws. Source recovered by exact bytecode match: solc v0.1.1+commit.6ff4cd6 with the optimizer on reproduces all 1096 bytes of the creation transaction.
Source Verified
1073 bytes. Source reconstructed: commit-reveal lottery by same developer as EarlyLottery (0x7af6af3d). 5 functions: submitSecret(bytes32), random(), payout(), payoutReady(), buyTicket(bytes32). Correct size match and all selectors confirmed with v0.1.5 optimizer ON. 935 diffs in optimizer layout -- exact compiler snapshot not found. 0.824 ETH remains locked since Aug 8 2015.
Historian Categories
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 (near-exact bytecode match).
View Verification ProofShow source code (Solidity)
contract Lottery {
uint startBlock;
uint numParticipants;
address[] participants;
uint64[] secrets;
mapping (address => bytes32) hashes;
mapping (address => uint) amounts;
function Lottery() { startBlock = block.number; }
function submitSecret(uint64 secret) {
if (!(block.number % 88 < 0x44 && block.number % 88 >= 0x30)) return;
if (sha3(bytes8(secret)) != hashes[msg.sender]) return;
participants.length++;
participants[participants.length - 1] = msg.sender;
secrets.length++;
secrets[secrets.length - 1] = secret;
}
function random() returns (uint64 r) {
for (uint i = 0; i < secrets.length; i++) {
r ^= secrets[i];
}
}
function payout() {
if (!payoutReady()) return;
uint winner = random() % participants.length;
participants[winner].call.value(this.balance - tx.gasprice * 25000)();
startBlock = block.number;
participants.length = 0;
secrets.length = 0;
numParticipants = 0;
}
function payoutReady() returns (bool) {
return block.number % 88 > 0x44 && block.number - startBlock > 0x44;
}
function buyTicket(bytes32 hash) {
if (block.number % 88 >= 0x28) return;
hashes[msg.sender] = hash;
amounts[msg.sender] += msg.value;
numParticipants++;
}
}External Links
Related contracts
EarlyLottery
Same deployerCommit-reveal lottery prototype deployed on 8 August 2015, the earlier draft of the EarlyLottery contract by the same developer.
0x7573ac...ad9fb4August 8, 2015Sha3
Same deployerA tiny utility contract that returns the SHA3 hash of a uint256 input.
0xb179a8...4bf09dAugust 9, 2015Sha3
Same deployerA tiny utility contract that returns the SHA3 hash of a uint256 input.
0x82000e...b0690aAugust 9, 2015Sha3
Same deployerA tiny utility contract that returns the SHA3 hash of a uint256 input.
0x627a6e...25bce8August 9, 2015LotteryPrototype
Same deployerThe first lottery contract deployed on Ethereum mainnet, created August 9, 2015 by one of the earliest recorded Ethereum users. Built, tested with two participa
0xcdd192...1b622cAugust 9, 2015EarlyLottery
Same deployerA commit-reveal lottery on an 88-block cycle, deployed August 9, 2015, ten days after genesis. Players commit a hashed secret, reveal it to earn one ticket per 0.1 ETH, and the winner is drawn from the XOR of all revealed secrets. Source recovered by exact bytecode match (solc v0.1.1).
0x7af6af...fbb992August 9, 2015