smartbugs-curated/dataset/unchecked_low_level_calls/0x07f7ecb66d788ab01dc93b9b7...

297 lines
5.9 KiB
Solidity

/*
* @source: etherscan.io
* @author: -
* @vulnerable_at_lines: 201,213
*/
pragma solidity ^0.4.21;
contract PoCGame
{
/**
* Modifiers
*/
modifier onlyOwner()
{
require(msg.sender == owner);
_;
}
modifier isOpenToPublic()
{
require(openToPublic);
_;
}
modifier onlyRealPeople()
{
require (msg.sender == tx.origin);
_;
}
modifier onlyPlayers()
{
require (wagers[msg.sender] > 0);
_;
}
/**
* Events
*/
event Wager(uint256 amount, address depositer);
event Win(uint256 amount, address paidTo);
event Lose(uint256 amount, address loser);
event Donate(uint256 amount, address paidTo, address donator);
event DifficultyChanged(uint256 currentDifficulty);
event BetLimitChanged(uint256 currentBetLimit);
/**
* Global Variables
*/
address private whale;
uint256 betLimit;
uint difficulty;
uint private randomSeed;
address owner;
mapping(address => uint256) timestamps;
mapping(address => uint256) wagers;
bool openToPublic;
uint256 totalDonated;
/**
* Constructor
*/
constructor(address whaleAddress, uint256 wagerLimit)
onlyRealPeople()
public
{
openToPublic = false;
owner = msg.sender;
whale = whaleAddress;
totalDonated = 0;
betLimit = wagerLimit;
}
/**
* Let the public play
*/
function OpenToThePublic()
onlyOwner()
public
{
openToPublic = true;
}
/**
* Adjust the bet amounts
*/
function AdjustBetAmounts(uint256 amount)
onlyOwner()
public
{
betLimit = amount;
emit BetLimitChanged(betLimit);
}
/**
* Adjust the difficulty
*/
function AdjustDifficulty(uint256 amount)
onlyOwner()
public
{
difficulty = amount;
emit DifficultyChanged(difficulty);
}
function() public payable { }
/**
* Wager your bet
*/
function wager()
isOpenToPublic()
onlyRealPeople()
payable
public
{
//You have to send exactly 0.01 ETH.
require(msg.value == betLimit);
//You cannot wager multiple times
require(wagers[msg.sender] == 0);
//log the wager and timestamp(block number)
timestamps[msg.sender] = block.number;
wagers[msg.sender] = msg.value;
emit Wager(msg.value, msg.sender);
}
/**
* method to determine winners and losers
*/
function play()
isOpenToPublic()
onlyRealPeople()
onlyPlayers()
public
{
uint256 blockNumber = timestamps[msg.sender];
if(blockNumber < block.number)
{
timestamps[msg.sender] = 0;
wagers[msg.sender] = 0;
uint256 winningNumber = uint256(keccak256(abi.encodePacked(blockhash(blockNumber), msg.sender)))%difficulty +1;
if(winningNumber == difficulty / 2)
{
payout(msg.sender);
}
else
{
//player loses
loseWager(betLimit / 2);
}
}
else
{
revert();
}
}
/**
* For those that just want to donate to the whale
*/
function donate()
isOpenToPublic()
public
payable
{
donateToWhale(msg.value);
}
/**
* Payout ETH to winner
*/
function payout(address winner)
internal
{
uint256 ethToTransfer = address(this).balance / 2;
winner.transfer(ethToTransfer);
emit Win(ethToTransfer, winner);
}
/**
* Payout ETH to whale
*/
function donateToWhale(uint256 amount)
internal
{
// <yes> <report> UNCHECKED_LL_CALLS
whale.call.value(amount)(bytes4(keccak256("donate()")));
totalDonated += amount;
emit Donate(amount, whale, msg.sender);
}
/**
* Payout ETH to whale when player loses
*/
function loseWager(uint256 amount)
internal
{
// <yes> <report> UNCHECKED_LL_CALLS
whale.call.value(amount)(bytes4(keccak256("donate()")));
totalDonated += amount;
emit Lose(amount, msg.sender);
}
/**
* ETH balance of contract
*/
function ethBalance()
public
view
returns (uint256)
{
return address(this).balance;
}
/**
* current difficulty of the game
*/
function currentDifficulty()
public
view
returns (uint256)
{
return difficulty;
}
/**
* current bet amount for the game
*/
function currentBetLimit()
public
view
returns (uint256)
{
return betLimit;
}
function hasPlayerWagered(address player)
public
view
returns (bool)
{
if(wagers[player] > 0)
{
return true;
}
else
{
return false;
}
}
/**
* For the UI to properly display the winner's pot
*/
function winnersPot()
public
view
returns (uint256)
{
return address(this).balance / 2;
}
/**
* A trap door for when someone sends tokens other than the intended ones so the overseers can decide where to send them.
*/
function transferAnyERC20Token(address tokenAddress, address tokenOwner, uint tokens)
public
onlyOwner()
returns (bool success)
{
return ERC20Interface(tokenAddress).transfer(tokenOwner, tokens);
}
}
//Define ERC20Interface.transfer, so PoCWHALE can transfer tokens accidently sent to it.
contract ERC20Interface
{
function transfer(address to, uint256 tokens) public returns (bool success);
}