pragma solidity ^0.4.24; /** Double% Earn 10% per hour, double your %ROI every hour you HODL! First hour: 10% Second hour: 20% Third hour: 40% ...etc... */ contract DoubleROI { using SafeMath for uint256; mapping(address => mapping (uint256 => uint256)) public investments; mapping(address => mapping (uint256 => uint256)) public joined; mapping(address => mapping (uint256 => uint256)) public referrer; mapping(address => bool) public hasRefferal; mapping(uint256 => uint256) public roundEndTime; bool public gameOpen; bool public roundEnded; uint256 public startTime; uint256 public roundCount; uint256 public coolDown = 10 minutes; uint256 public step = 2400; uint256 public minimum = 10 finney; uint256 public maximum = 5 ether; uint256 public stakingRequirement = 0.5 ether; address public ownerWallet; address public owner; event Invest(address investor, uint256 amount); event Withdraw(address investor, uint256 amount); event Bounty(address hunter, uint256 amount); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Сonstructor Sets the original roles of the contract */ constructor(uint256 _startTime) public { startTime = _startTime; roundCount++; owner = msg.sender; ownerWallet = msg.sender; } /** * @dev Modifiers */ modifier onlyOwner() { require(msg.sender == owner); _; } modifier gameStarted() { require(now >= startTime); _; } /** * @dev Allows current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. * @param newOwnerWallet The address to transfer ownership to. */ function transferOwnership(address newOwner, address newOwnerWallet) public onlyOwner { require(newOwner != address(0)); emit OwnershipTransferred(owner, newOwner); owner = newOwner; ownerWallet = newOwnerWallet; } /** * @dev Investments */ function () public payable gameStarted() { buy(0x0); } function buy(address _referredBy) public payable gameStarted() { require(msg.value >= minimum); require(msg.value <= maximum); if (gameOpen == true && roundEnded == true && now > roundEndTime[roundCount] + coolDown) { advanceRound(); } if (now >= startTime) { gameOpen = true; } address _customerAddress = msg.sender; if( // is this a referred purchase? _referredBy != 0x0000000000000000000000000000000000000000 && // no cheating! _referredBy != _customerAddress && // does the referrer have at least X whole tokens? // i.e is the referrer a godly chad masternode investments[_referredBy][roundCount] >= stakingRequirement || // is this a referred purchase? _referredBy != 0x0000000000000000000000000000000000000000 && // no cheating! _referredBy != _customerAddress && // does the referrer have at least X whole tokens? // i.e is the referrer a godly chad masternode hasRefferal[msg.sender] == true ){ // wealth redistribution hasRefferal[msg.sender] = true; referrer[_referredBy][roundCount] = referrer[_referredBy][roundCount].add(msg.value.mul(5).div(100)); } if (investments[msg.sender][roundCount] > 0){ withdraw(); } investments[msg.sender][roundCount] = investments[msg.sender][roundCount].add(msg.value); joined[msg.sender][roundCount] = block.timestamp; ownerWallet.transfer(msg.value.mul(5).div(100)); emit Invest(msg.sender, msg.value); } /** * @dev Evaluate current balance * @param _address Address of investor */ function getBalance(address _address) view public returns (uint256) { uint256 minutesCount = now.sub(joined[_address][roundCount]).div(1 minutes); // update roi multiplier // 10% flat during first hour // 20% flat during second hour // 40% flat during third hour uint256 userROIMultiplier = 2**(minutesCount / 60); uint256 percent; uint256 balance; for(uint i=1; i<userROIMultiplier; i=i*2){ // add each percent - // first hour is 10% // second hour is 20% // third hour is 40% // etc - add all these up percent = investments[_address][roundCount].mul(step).div(1000) * i; balance += percent.mul(60).div(1440); } // Finally, add the balance for the current multiplier percent = investments[_address][roundCount].mul(step).div(1000) * userROIMultiplier; balance += percent.mul(minutesCount % 60).div(1440); return balance; } /** * @dev Withdraw dividends from contract */ function withdraw() public returns (bool) { require(joined[msg.sender][roundCount] > 0); uint256 balance = getBalance(msg.sender); // Reset ROI mulitplier of user joined[msg.sender][roundCount] = block.timestamp; if (address(this).balance > balance){ if (balance > 0){ msg.sender.transfer(balance); emit Withdraw(msg.sender, balance); } return true; } else { if (balance > 0) { msg.sender.transfer(address(this).balance); roundEnded = true; roundEndTime[roundCount] = now; emit Withdraw(msg.sender, balance); } return true; } } /** * @dev Bounty reward */ function bounty() public { uint256 refBalance = checkReferral(msg.sender); if(refBalance >= minimum) { if (address(this).balance > refBalance) { referrer[msg.sender][roundCount] = 0; msg.sender.transfer(refBalance); emit Bounty(msg.sender, refBalance); } } } /** * @dev Gets balance of the sender address. * @return An uint256 representing the amount owned by the msg.sender. */ function checkBalance() public view returns (uint256) { return getBalance(msg.sender); } /** * @dev Gets investments of the specified address. * @param _investor The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ function checkInvestments(address _investor) public view returns (uint256) { return investments[_investor][roundCount]; } /** * @dev Gets referrer balance of the specified address. * @param _hunter The address of the referrer * @return An uint256 representing the referral earnings. */ function checkReferral(address _hunter) public view returns (uint256) { return referrer[_hunter][roundCount]; } /** *@dev advances round and clears storage */ function advanceRound() internal { roundEnded = false; roundCount++; } } /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } }
0.4.24