smartbugs-curated/dataset/other/open_address_lottery.sol

105 lines
4.0 KiB
Solidity

/*
* @source: https://etherscan.io/address/0x741f1923974464efd0aa70e77800ba5d9ed18902#code
* @vulnerable_at_lines: 91
*/
pragma solidity ^0.4.19;
/*
* This is a distributed lottery that chooses random addresses as lucky addresses. If these
* participate, they get the jackpot: 7 times the price of their bet.
* Of course one address can only win once. The owner regularly reseeds the secret
* seed of the contract (based on which the lucky addresses are chosen), so if you did not win,
* just wait for a reseed and try again!
*
* Jackpot chance: 1 in 8
* Ticket price: Anything larger than (or equal to) 0.1 ETH
* Jackpot size: 7 times the ticket price
*
* HOW TO PARTICIPATE: Just send any amount greater than (or equal to) 0.1 ETH to the contract's address
* Keep in mind that your address can only win once
*
* If the contract doesn't have enough ETH to pay the jackpot, it sends the whole balance.
https://www.reddit.com/r/ethdev/comments/7wp363/how_does_this_honeypot_work_it_seems_like_a/
*/
contract OpenAddressLottery{
struct SeedComponents{
uint component1;
uint component2;
uint component3;
uint component4;
}
address owner; //address of the owner
uint private secretSeed; //seed used to calculate number of an address
uint private lastReseed; //last reseed - used to automatically reseed the contract every 1000 blocks
uint LuckyNumber = 7; //if the number of an address equals 7, it wins
mapping (address => bool) winner; //keeping track of addresses that have already won
function OpenAddressLottery() {
owner = msg.sender;
reseed(SeedComponents((uint)(block.coinbase), block.difficulty, block.gaslimit, block.timestamp)); //generate a quality random seed
}
function participate() payable {
if(msg.value<0.1 ether)
return; //verify ticket price
// make sure he hasn't won already
require(winner[msg.sender] == false);
if(luckyNumberOfAddress(msg.sender) == LuckyNumber){ //check if it equals 7
winner[msg.sender] = true; // every address can only win once
uint win=msg.value*7; //win = 7 times the ticket price
if(win>this.balance) //if the balance isnt sufficient...
win=this.balance; //...send everything we've got
msg.sender.transfer(win);
}
if(block.number-lastReseed>1000) //reseed if needed
reseed(SeedComponents((uint)(block.coinbase), block.difficulty, block.gaslimit, block.timestamp)); //generate a quality random seed
}
function luckyNumberOfAddress(address addr) constant returns(uint n){
// calculate the number of current address - 1 in 8 chance
n = uint(keccak256(uint(addr), secretSeed)[0]) % 8;
}
function reseed(SeedComponents components) internal {
secretSeed = uint256(keccak256(
components.component1,
components.component2,
components.component3,
components.component4
)); //hash the incoming parameters and use the hash to (re)initialize the seed
lastReseed = block.number;
}
function kill() {
require(msg.sender==owner);
selfdestruct(msg.sender);
}
function forceReseed() { //reseed initiated by the owner - for testing purposes
require(msg.sender==owner);
// <yes> <report> OTHER - uninitialized storage
SeedComponents s;
s.component1 = uint(msg.sender);
s.component2 = uint256(block.blockhash(block.number - 1));
s.component3 = block.difficulty*(uint)(block.coinbase);
s.component4 = tx.gasprice * 7;
reseed(s); //reseed
}
function () payable { //if someone sends money without any function call, just assume he wanted to participate
if(msg.value>=0.1 ether && msg.sender!=owner) //owner can't participate, he can only fund the jackpot
participate();
}
}