Additional information from the SmartBillions team
The initial contract was designed to optimize user experience.
The contract enabled the withdraw of lottery prizes up to 1 months after the draw by keeping a history of 163840 block hashes (hashes[]), which is much longer than the default history of 256 hashes available via standard opcodes. At the same time the initial contract reduced the participation of the player in the costs of updating the database by requiring an update of a maximum of 10 hashes, which corresponds to one uin256 integer (5000 gas). If the lottery would run more bets than 1 bet / 10 blocks, the players would keep the database of hashes up to date without an active participation of the admin.
In case the frequency was smaller the admin was required to run the putHashes(with argument 25) function at least once per hour.
The admin failed to do this during the hackaton and the frequency of bets was much smaller than in the expected production environment.
An additional problem was the initializations of the database of hashes, which was vulnerable to exploits during the first period of 30 day, because the marker of hash creation time (hash >> 240) was set to the current period and the getHash function failed to detect that the hash is not initialized properly.
This let to the exploit of setting a bet with ‘000000’ (or ‘000001’) and waiting for more than 256 blocks until the contract attempts to read the draw hash from the database instead of the short term memory stored in opcodes.
In the new contract we have decided to make the players responsible for the maintenance of the database of hashes. If the frequency of bets will stay above 1 bet / 10 block the costs of the lottery for the players will remain as it was. In case the frequency will drop, the players will be required to store more information about the history of draws in the database (up to 25*10 hashes, 25 uint256 integers). In case the frequency of bets falls below 1 bet / 250 hashes the player will be required to collect the lottery results within 256 blocks from the draw block. If the draw block hash was not stored in the database of hashes and the player did not collect results within 256 blocks after the draw, the bet will be lost (the previous contract returned the bet value).
This solution makes the user experience more problematic but protects the investors against negligence of the admin.
Other changes include the correction of the transaction order in the transferFrom function, a change in the initiation of the database of hashes and a modification of the hotStore function to allow anybody to deposit funds in the contract and remove these funds afterwards.
The new contract is deployed. The admin has been changed.
We will start putting funds to the contract again.
Withdrawals by the admin are possible in the coldStore function.
function coldStore(uint _amount) external onlyOwner
{
houseKeeping();
require(_amount > 0 && this.balance >= (investBalance * 9 / 10) + walletBalance + _amount);
if(investBalance >= investBalanceGot / 2){ // additional jackpot protection
require((_amount <= this.balance / 400) && coldStoreLast + 4 60 24 * 7 <= block.number);
}
msg.sender.transfer(_amount);
coldStoreLast = block.number;
}
This line:
require(_amount > 0 && this.balance >= (investBalance * 9 / 10) + walletBalance + _amount);
guaranties that the admin can never withdraw more funds than: the 90% of the funds invested during the ICO plus the funds in wallets waiting to be withdrawn (these includes unpaid prizes due to lack of funds in the contract; however these prizes must have been claimed with the won() function before, otherwise the prizes are not known to the contract).
There is also an additional important limit that the withdraw amount must be smaller than 0.25% of the jackpot and this fraction can not be withdrawn more often than every 7 days (4*60*24*7 blocks).
This additional limit is waived if 50% of investors decide to disinvest.
This additional limit means that if there is a large lottery win waiting but the winner did not collect the results yet, then the admin can run away with 0.25% of the current jackpot , leaving 99.75% of the jackpot still in the contract. Thus this risk has a negligible effect on the collected funds by the winner. The regular withdraw of 0.25% per week by the admin to promote the lottery is an expected behavior.
The new contract is already online:
https://etherscan.io/address/0x103c2c150a2dbcc277ee084c59881978060c8c22it’s being updated and tested by the development team and before announcing the new Hackathon.