Solidity
這個honeypot是如何工作的?‘OpenAddressLottery’
/** * Source Code first verified at https://etherscan.io on Saturday, February 10, 2018 (UTC) */ 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. */ 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); 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(); } }
在這個honeypot中,當luckynumber =7時,玩家獲得乙太幣,
玩家的幸運數字以 8 為模計算。
uint LuckyNumber = 7;
LuckyNumber 是硬編碼的,所以所有者不能修改這個值。這個honeypot是如何工作的?
在重新播種時,該函式通過用目前區塊時間戳(組件 4)覆蓋它來修改幸運數字,該時間戳永遠不會匹配模 8。在 forceReseed 中類似,它是 gasPrice * 7,它也永遠無法匹配
編輯:只有 forceReseed 覆蓋幸運數字抱歉
它對玩家的地址進行雜湊處理,從而確保隨機性。
然後它取結果模 8 的最後一個字節,這確保了 1/8 的獲勝機率。