pragma solidity ^0.4.24;
/***
* @title -Midnight Run v0.1.0
*
*
* ███╗ ███╗██╗██████╗ ███╗ ██╗██╗ ██████╗ ██╗ ██╗████████╗ ██████╗ ██╗ ██╗███╗ ██╗
* ████╗ ████║██║██╔══██╗████╗ ██║██║██╔════╝ ██║ ██║╚══██╔══╝ ██╔══██╗██║ ██║████╗ ██║
* ██╔████╔██║██║██║ ██║██╔██╗ ██║██║██║ ███╗███████║ ██║ ██████╔╝██║ ██║██╔██╗ ██║
* ██║╚██╔╝██║██║██║ ██║██║╚██╗██║██║██║ ██║██╔══██║ ██║ ██╔══██╗██║ ██║██║╚██╗██║
* ██║ ╚═╝ ██║██║██████╔╝██║ ╚████║██║╚██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
* ╚═╝ ╚═╝╚═╝╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
* ┌─────────────────────────┐
* │https://midnightrun.live │
* └─────────────────────────┘
*
* This product is provided for public use without any guarantee or recourse to appeal
*
* Payouts are collectible daily after 00:00 UTC
* Referral rewards are distributed automatically.
* The last 5 in before 00:00 UTC win the midnight prize.
*
* By sending ETH to this contract you are agreeing to the terms set out in the logic listed below.
*
* WARNING1: Do not invest more than you can afford.
* WARNING2: You can earn.
*/
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address private _owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
_owner = msg.sender;
}
/**
* @return the address of the owner.
*/
function owner() public view returns(address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns(bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/***
* __ __ __ _ __ _ ___ __ __ _ _____ ___ __ ________
* | V |/ \| | \| | / _//__\| \| |_ _| _ \/ \ / _/_ _|
* | \_/ | /\ | | | ' | | \_| \/ | | ' | | | | v / /\ | \__ | |
* |_| |_|_||_|_|_|\__| \__/\__/|_|\__| |_| |_|_\_||_|\__/ |_|
*/
contract MidnightRun is Ownable {
using SafeMath
for uint;
modifier isHuman() {
uint32 size;
address investor = msg.sender;
assembly {
size: = extcodesize(investor)
}
if (size > 0) {
revert("Inhuman");
}
_;
}
event DailyDividendPayout(address indexed _address, uint value, uint periodCount, uint percent, uint time);
event ReferralPayout(address indexed _addressFrom, address indexed _addressTo, uint value, uint percent, uint time);
event MidnightRunPayout(address indexed _address, uint value, uint totalValue, uint userValue, uint time);
uint public period = 24 hours;
uint public startTime = 1537833600; // Tue, 25 Sep 2018 00:00:00 +0000 UTC
uint public dailyDividendPercent = 300; //3%
uint public referredDividendPercent = 330; //3.3%
uint public referrerPercent = 250; //2.5%
uint public minBetLevel = 0.01 ether;
uint public referrerAndOwnerPercent = 2000; //20%
uint public currentStakeID = 1;
struct DepositInfo {
uint value;
uint firstBetTime;
uint lastBetTime;
uint lastPaymentTime;
uint nextPayAfterTime;
bool isExist;
uint id;
uint referrerID;
}
mapping(address => DepositInfo) public investorToDepostIndex;
mapping(uint => address) public idToAddressIndex;
// Jackpot
uint public midnightPrizePercent = 1000; //10%
uint public midnightPrize = 0;
uint public nextPrizeTime = startTime + period;
uint public currentPrizeStakeID = 0;
struct MidnightRunDeposit {
uint value;
address user;
}
mapping(uint => MidnightRunDeposit) public stakeIDToDepositIndex;
/**
* Constructor no need for unnecessary work in here.
*/
constructor() public {
}
/**
* Fallback and entrypoint for deposits.
*/
function() public payable isHuman {
if (msg.value == 0) {
collectPayoutForAddress(msg.sender);
} else {
uint refId = 1;
address referrer = bytesToAddress(msg.data);
if (investorToDepostIndex[referrer].isExist) {
refId = investorToDepostIndex[referrer].id;
}
deposit(refId);
}
}
/**
* Reads the given bytes into an addtress
*/
function bytesToAddress(bytes bys) private pure returns(address addr) {
assembly {
addr: = mload(add(bys, 20))
}
}
/**
* Put some funds into the contract for the prize
*/
function addToMidnightPrize() public payable onlyOwner {
midnightPrize += msg.value;
}
/**
* Get the time of the next payout - calculated
*/
function getNextPayoutTime() public view returns(uint) {
if (now<startTime) return startTime + period;
return startTime + ((now.sub(startTime)).div(period)).mul(period) + period;
}
/**
* Make a deposit into the contract
*/
function deposit(uint _referrerID) public payable isHuman {
require(_referrerID <= currentStakeID, "Who referred you?");
require(msg.value >= minBetLevel, "Doesn't meet minimum stake.");
// when is next midnight ?
uint nextPayAfterTime = getNextPayoutTime();
if (investorToDepostIndex[msg.sender].isExist) {
if (investorToDepostIndex[msg.sender].nextPayAfterTime < now) {
collectPayoutForAddress(msg.sender);
}
investorToDepostIndex[msg.sender].value += msg.value;
investorToDepostIndex[msg.sender].lastBetTime = now;
} else {
DepositInfo memory newDeposit;
newDeposit = DepositInfo({
value: msg.value,
firstBetTime: now,
lastBetTime: now,
lastPaymentTime: 0,
nextPayAfterTime: nextPayAfterTime,
isExist: true,
id: currentStakeID,
referrerID: _referrerID
});
investorToDepostIndex[msg.sender] = newDeposit;
idToAddressIndex[currentStakeID] = msg.sender;
currentStakeID++;
}
if (now > nextPrizeTime) {
doMidnightRun();
}
currentPrizeStakeID++;
MidnightRunDeposit memory midnitrunDeposit;
midnitrunDeposit.user = msg.sender;
midnitrunDeposit.value = msg.value;
stakeIDToDepositIndex[currentPrizeStakeID] = midnitrunDeposit;
// contribute to the Midnight Run Prize
midnightPrize += msg.value.mul(midnightPrizePercent).div(10000);
// Is there a referrer to be paid?
if (investorToDepostIndex[msg.sender].referrerID != 0) {
uint refToPay = msg.value.mul(referrerPercent).div(10000);
// Referral Fee
idToAddressIndex[investorToDepostIndex[msg.sender].referrerID].transfer(refToPay);
// Team and advertising fee
owner().transfer(msg.value.mul(referrerAndOwnerPercent - referrerPercent).div(10000));
emit ReferralPayout(msg.sender, idToAddressIndex[investorToDepostIndex[msg.sender].referrerID], refToPay, referrerPercent, now);
} else {
// Team and advertising fee
owner().transfer(msg.value.mul(referrerAndOwnerPercent).div(10000));
}
}
/**
* Collect payout for the msg.sender
*/
function collectPayout() public isHuman {
collectPayoutForAddress(msg.sender);
}
/**
* Collect payout for the given address
*/
function getRewardForAddress(address _address) public onlyOwner {
collectPayoutForAddress(_address);
}
/**
*
*/
function collectPayoutForAddress(address _address) internal {
require(investorToDepostIndex[_address].isExist == true, "Who are you?");
require(investorToDepostIndex[_address].nextPayAfterTime < now, "Not yet.");
uint periodCount = now.sub(investorToDepostIndex[_address].nextPayAfterTime).div(period).add(1);
uint percent = dailyDividendPercent;
if (investorToDepostIndex[_address].referrerID > 0) {
percent = referredDividendPercent;
}
uint toPay = periodCount.mul(investorToDepostIndex[_address].value).div(10000).mul(percent);
investorToDepostIndex[_address].lastPaymentTime = now;
investorToDepostIndex[_address].nextPayAfterTime += periodCount.mul(period);
// protect contract - this could result in some bad luck - but not much
if (toPay.add(midnightPrize) < address(this).balance.sub(msg.value))
{
_address.transfer(toPay);
emit DailyDividendPayout(_address, toPay, periodCount, percent, now);
}
}
/**
* Perform the Midnight Run
*/
function doMidnightRun() public isHuman {
require(now>nextPrizeTime , "Not yet");
// set the next prize time to the next payout time (MidnightRun)
nextPrizeTime = getNextPayoutTime();
if (currentPrizeStakeID > 5) {
uint toPay = midnightPrize;
midnightPrize = 0;
if (toPay > address(this).balance){
toPay = address(this).balance;
}
uint totalValue = stakeIDToDepositIndex[currentPrizeStakeID].value + stakeIDToDepositIndex[currentPrizeStakeID - 1].value + stakeIDToDepositIndex[currentPrizeStakeID - 2].value + stakeIDToDepositIndex[currentPrizeStakeID - 3].value + stakeIDToDepositIndex[currentPrizeStakeID - 4].value;
stakeIDToDepositIndex[currentPrizeStakeID].user.transfer(toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID].value).div(totalValue));
emit MidnightRunPayout(stakeIDToDepositIndex[currentPrizeStakeID].user, toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID].value).div(totalValue), totalValue, stakeIDToDepositIndex[currentPrizeStakeID].value, now);
stakeIDToDepositIndex[currentPrizeStakeID - 1].user.transfer(toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 1].value).div(totalValue));
emit MidnightRunPayout(stakeIDToDepositIndex[currentPrizeStakeID - 1].user, toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 1].value).div(totalValue), totalValue, stakeIDToDepositIndex[currentPrizeStakeID - 1].value, now);
stakeIDToDepositIndex[currentPrizeStakeID - 2].user.transfer(toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 2].value).div(totalValue));
emit MidnightRunPayout(stakeIDToDepositIndex[currentPrizeStakeID - 2].user, toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 2].value).div(totalValue), totalValue, stakeIDToDepositIndex[currentPrizeStakeID - 2].value, now);
stakeIDToDepositIndex[currentPrizeStakeID - 3].user.transfer(toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 3].value).div(totalValue));
emit MidnightRunPayout(stakeIDToDepositIndex[currentPrizeStakeID - 3].user, toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 3].value).div(totalValue), totalValue, stakeIDToDepositIndex[currentPrizeStakeID - 3].value, now);
stakeIDToDepositIndex[currentPrizeStakeID - 4].user.transfer(toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 4].value).div(totalValue));
emit MidnightRunPayout(stakeIDToDepositIndex[currentPrizeStakeID - 4].user, toPay.mul(stakeIDToDepositIndex[currentPrizeStakeID - 4].value).div(totalValue), totalValue, stakeIDToDepositIndex[currentPrizeStakeID - 4].value, now);
}
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts 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;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
{
"compilationTarget": {
"MidnightRun.sol": "MidnightRun"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[],"name":"addToMidnightPrize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"stakeIDToDepositIndex","outputs":[{"name":"value","type":"uint256"},{"name":"user","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minBetLevel","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"doMidnightRun","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"referrerPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"idToAddressIndex","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentPrizeStakeID","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"referredDividendPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"midnightPrizePercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"getRewardForAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_referrerID","type":"uint256"}],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"dailyDividendPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"investorToDepostIndex","outputs":[{"name":"value","type":"uint256"},{"name":"firstBetTime","type":"uint256"},{"name":"lastBetTime","type":"uint256"},{"name":"lastPaymentTime","type":"uint256"},{"name":"nextPayAfterTime","type":"uint256"},{"name":"isExist","type":"bool"},{"name":"id","type":"uint256"},{"name":"referrerID","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"collectPayout","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"referrerAndOwnerPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentStakeID","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"period","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"midnightPrize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextPrizeTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextPayoutTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_address","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"periodCount","type":"uint256"},{"indexed":false,"name":"percent","type":"uint256"},{"indexed":false,"name":"time","type":"uint256"}],"name":"DailyDividendPayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_addressFrom","type":"address"},{"indexed":true,"name":"_addressTo","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"percent","type":"uint256"},{"indexed":false,"name":"time","type":"uint256"}],"name":"ReferralPayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_address","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"totalValue","type":"uint256"},{"indexed":false,"name":"userValue","type":"uint256"},{"indexed":false,"name":"time","type":"uint256"}],"name":"MidnightRunPayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]