pragma solidity ^0.4.25;
interface DSG {
function gamingDividendsReception() payable external;
}
contract CoinFlipper{
using SafeMath for uint256;
address constant public DSG_ADDRESS = 0x696826C18A6Bc9Be4BBfe3c3A6BB9f5a69388687;
uint256 public totalDividends;
uint256 public totalWinnings;
uint256 public totalTurnover;
uint256 public maxBet;
uint256 public minBet;
uint256 public minContractBalance;
uint256 public minBetForJackpot;
uint256 public jackpotBalance;
uint256 public nextPayout;
uint256 public ownerDeposit;
address[2] public owners;
address[2] public candidates;
bool public paused;
mapping (address => Bet) public usersBets;
struct Bet {
uint256 blockNumber;
uint8 coin;
uint256 bet;
}
modifier onlyOwners() {
require(msg.sender == owners[0] || msg.sender == owners[1]);
_;
}
modifier checkBlockNumber(){
uint256 blockNumber = usersBets[msg.sender].blockNumber;
if(block.number.sub(blockNumber) >= 250 && blockNumber > 0){
emit Result(msg.sender, 0, 1000, 0, jackpotBalance, 0, usersBets[msg.sender].bet);
delete usersBets[msg.sender];
}
else{
_;
}
}
constructor(address secondOwner) public payable{
owners[0] = msg.sender;
owners[1] = secondOwner;
ownerDeposit = msg.value;
jackpotBalance = jackpotBalance.add(msg.value.div(100));
}
function play(uint8 coin) public payable checkBlockNumber{
uint256 bet = msg.value;
require(getContractBalance() > bet.add(bet).add(jackpotBalance), "Not enough ETH in contract");
require(paused == false, "Game was stopped");
require(bet >= minBet && bet <= maxBet, "Amount should be within range");
require(usersBets[msg.sender].bet == 0, "You have already bet");
usersBets[msg.sender].bet = bet;
usersBets[msg.sender].blockNumber = block.number;
usersBets[msg.sender].coin = coin;
totalTurnover = totalTurnover.add(bet);
emit PlaceBet(msg.sender, bet, coin, now);
}
function result() public checkBlockNumber{
require(blockhash(usersBets[msg.sender].blockNumber) != 0, "Your time to determine the result has come out or not yet come");
uint256 bet = usersBets[msg.sender].bet;
uint8 coin = usersBets[msg.sender].coin;
uint256 totalWinAmount;
uint256 winRate = getWinningRate(usersBets[msg.sender].bet);
uint256 r = _random(1200);
if(((r > 0 && r < 200) || (r > 400 && r < 600) || (r > 800 && r < 1000)) && coin == 1){
totalWinAmount = totalWinAmount.add(bet.add(bet.mul(winRate).div(100)));
jackpotBalance = jackpotBalance.add(bet.mul(100 - winRate).div(1000));
}
if(((r > 200 && r < 400) || (r > 600 && r < 800) || (r > 1000 && r < 1200)) && coin == 0){
totalWinAmount = totalWinAmount.add(bet.add(bet.mul(winRate).div(100)));
jackpotBalance = jackpotBalance.add(bet.mul(100 - winRate).div(1000));
}
if(bet >= minBetForJackpot && r == 0 && jackpotBalance > 0){
totalWinAmount = totalWinAmount.add(jackpotBalance).add(bet.add(bet.mul(winRate).div(100)));
delete jackpotBalance;
}
if(totalWinAmount > 0){
msg.sender.transfer(totalWinAmount);
totalWinnings = totalWinnings.add(totalWinAmount);
}
else{
jackpotBalance = jackpotBalance.add(bet.div(100));
}
delete usersBets[msg.sender];
emit Result(msg.sender, coin, r, totalWinAmount, jackpotBalance, winRate, bet);
}
function sendDividends() public {
require(getContractBalance() > minContractBalance && now > nextPayout, "You cannot send dividends");
DSG DSG0 = DSG(DSG_ADDRESS);
uint256 balance = getContractBalance();
uint256 dividends = balance.sub(minContractBalance);
nextPayout = now.add(7 days);
totalDividends = totalDividends.add(dividends);
DSG0.gamingDividendsReception.value(dividends)();
emit Dividends(balance, dividends, now);
}
function getWinningRate(uint256 eth) public view returns(uint8){
uint256 x = maxBet.sub(minBet).div(4);
uint8 rate;
if(eth >= minBet && eth <= minBet.add(x)){
rate = 95;
}
else if(eth >= minBet.add(x.mul(1)) && eth <= minBet.add(x.mul(2))){
rate = 96;
}
else if(eth >= minBet.add(x.mul(2)) && eth <= minBet.add(x.mul(3))){
rate = 97;
}
else if(eth >= minBet.add(x.mul(3)) && eth <= minBet.add(x.mul(4))){
rate = 98;
}
else{
rate = 95;
}
return rate;
}
function getContractBalance() public view returns (uint256) {
return address(this).balance;
}
function _random(uint256 max) private view returns(uint256){
bytes32 hash = blockhash(usersBets[msg.sender].blockNumber);
return uint256(keccak256(abi.encode(hash, now, msg.sender))) % max;
}
function deposit() public payable onlyOwners{
ownerDeposit = ownerDeposit.add(msg.value);
jackpotBalance = jackpotBalance.add(msg.value.div(100));
}
function sendOwnerDeposit(address recipient) public onlyOwners{
require(paused == true, 'Game was not stopped');
uint256 contractBalance = getContractBalance();
if(contractBalance >= ownerDeposit){
recipient.transfer(ownerDeposit);
}
else{
recipient.transfer(contractBalance);
}
delete jackpotBalance;
delete ownerDeposit;
}
function pauseGame(bool option) public onlyOwners{
paused = option;
}
function setMinBet(uint256 eth) public onlyOwners{
minBet = eth;
}
function setMaxBet(uint256 eth) public onlyOwners{
maxBet = eth;
}
function setMinBetForJackpot(uint256 eth) public onlyOwners{
minBetForJackpot = eth;
}
function setMinContractBalance(uint256 eth) public onlyOwners{
minContractBalance = eth;
}
function transferOwnership(address newOwnerAddress, uint8 k) public onlyOwners {
candidates[k] = newOwnerAddress;
}
function confirmOwner(uint8 k) public {
require(msg.sender == candidates[k]);
owners[k] = candidates[k];
}
event Dividends(
uint256 balance,
uint256 dividends,
uint256 timestamp
);
event Jackpot(
address indexed player,
uint256 jackpot,
uint256 timestamp
);
event PlaceBet(
address indexed player,
uint256 bet,
uint256 coin,
uint256 timestamp
);
event Result(
address indexed player,
uint256 indexed coin,
uint256 indexed random,
uint256 totalWinAmount,
uint256 jackpotBalance,
uint256 winRate,
uint256 bet
);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) { return 0; }
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
{
"compilationTarget": {
"CoinFlipper.sol": "CoinFlipper"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"owners","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"jackpotBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"eth","type":"uint256"}],"name":"setMinContractBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"eth","type":"uint256"}],"name":"setMinBetForJackpot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"eth","type":"uint256"}],"name":"getWinningRate","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxBet","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minBetForJackpot","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidates","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"option","type":"bool"}],"name":"pauseGame","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"coin","type":"uint8"}],"name":"play","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalTurnover","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"result","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minContractBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwnerAddress","type":"address"},{"name":"k","type":"uint8"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ownerDeposit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextPayout","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"sendOwnerDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"eth","type":"uint256"}],"name":"setMaxBet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"eth","type":"uint256"}],"name":"setMinBet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minBet","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalDividends","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"sendDividends","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalWinnings","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DSG_ADDRESS","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"usersBets","outputs":[{"name":"blockNumber","type":"uint256"},{"name":"coin","type":"uint8"},{"name":"bet","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"k","type":"uint8"}],"name":"confirmOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"secondOwner","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"balance","type":"uint256"},{"indexed":false,"name":"dividends","type":"uint256"},{"indexed":false,"name":"timestamp","type":"uint256"}],"name":"Dividends","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"player","type":"address"},{"indexed":false,"name":"jackpot","type":"uint256"},{"indexed":false,"name":"timestamp","type":"uint256"}],"name":"Jackpot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"player","type":"address"},{"indexed":false,"name":"bet","type":"uint256"},{"indexed":false,"name":"coin","type":"uint256"},{"indexed":false,"name":"timestamp","type":"uint256"}],"name":"PlaceBet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"player","type":"address"},{"indexed":true,"name":"coin","type":"uint256"},{"indexed":true,"name":"random","type":"uint256"},{"indexed":false,"name":"totalWinAmount","type":"uint256"},{"indexed":false,"name":"jackpotBalance","type":"uint256"},{"indexed":false,"name":"winRate","type":"uint256"},{"indexed":false,"name":"bet","type":"uint256"}],"name":"Result","type":"event"}]