pragma solidity ^0.4.23;
contract Random {
uint public ticketsNum = 0;
mapping(uint => address) internal tickets;
mapping(uint => bool) internal payed_back;
uint32 public random_num = 0;
uint public liveBlocksNumber = 5760;
uint public startBlockNumber = 0;
uint public endBlockNumber = 0;
string public constant name = "Random Daily Lottery";
string public constant symbol = "RND";
uint public constant decimals = 0;
uint public constant onePotWei = 10000000000000000; // 1 ticket cost is 0.01 ETH
address public inv_contract = 0x1d9Ed8e4c1591384A4b2fbd005ccCBDc58501cc0; // investing contract
address public rtm_contract = 0x67e5e779bfc7a93374f273dcaefce0db8b3559c2; // team contract
address manager;
uint public winners_count = 0;
uint public last_winner = 0;
uint public others_prize = 0;
uint public fee_balance = 0;
bool public autopayfee = true;
// Events
// This generates a publics event on the blockchain that will notify clients
event Buy(address indexed sender, uint eth);
event Withdraw(address indexed sender, address to, uint eth);
event Transfer(address indexed from, address indexed to, uint value);
event TransferError(address indexed to, uint value); // event (error): sending ETH from the contract was failed
event PayFee(address _to, uint value);
// methods with following modifier can only be called by the manager
modifier onlyManager() {
require(msg.sender == manager);
_;
}
// constructor
constructor() public {
manager = msg.sender;
startBlockNumber = block.number - 1;
endBlockNumber = startBlockNumber + liveBlocksNumber;
}
/// function for straight tickets purchase (sending ETH to the contract address)
function() public payable {
emit Transfer(msg.sender, 0, 0);
require(block.number < endBlockNumber || msg.value < 1000000000000000000);
if (msg.value > 0 && last_winner == 0) {
uint val = msg.value / onePotWei;
uint i = 0;
for(i; i < val; i++) { tickets[ticketsNum+i] = msg.sender; }
ticketsNum += val;
emit Buy(msg.sender, msg.value);
}
if (block.number >= endBlockNumber) {
EndLottery();
}
}
/// function for ticket sending from owner's address to designated address
function transfer(address _to, uint _ticketNum) public {
require(msg.sender == tickets[_ticketNum] && _to != address(0));
tickets[_ticketNum] = _to;
emit Transfer(msg.sender, _to, _ticketNum);
}
/// manager's opportunity to write off ETH from the contract, in a case of unforseen contract blocking (possible in only case of more than 24 hours from the moment of lottery ending had passed and a new one has not started)
function manager_withdraw() onlyManager public {
require(block.number >= endBlockNumber + liveBlocksNumber);
msg.sender.transfer(address(this).balance);
}
/// lottery ending
function EndLottery() public payable returns (bool success) {
require(block.number >= endBlockNumber);
uint tn = ticketsNum;
if(tn < 3) {
tn = 0;
if(msg.value > 0) { msg.sender.transfer(msg.value); }
startNewDraw(0);
return false;
}
uint pf = prizeFund();
uint jp1 = percent(pf, 10);
uint jp2 = percent(pf, 4);
uint jp3 = percent(pf, 1);
uint lastbet_prize = onePotWei*10;
if(tn < 100) { lastbet_prize = onePotWei; }
if(last_winner == 0) {
winners_count = percent(tn, 4) + 3;
uint prizes = jp1 + jp2 + jp3 + lastbet_prize*2;
uint full_prizes = jp1 + jp2 + jp3 + ( lastbet_prize * (winners_count+1)/10 );
if(winners_count < 10) {
if(prizes > pf) {
others_prize = 0;
} else {
others_prize = pf - prizes;
}
} else {
if(full_prizes > pf) {
others_prize = 0;
} else {
others_prize = pf - full_prizes;
}
}
sendEth(tickets[getWinningNumber(1)], jp1);
sendEth(tickets[getWinningNumber(2)], jp2);
sendEth(tickets[getWinningNumber(3)], jp3);
last_winner += 3;
sendEth(msg.sender, lastbet_prize + msg.value);
return true;
}
if(last_winner < winners_count && others_prize > 0) {
uint val = others_prize / winners_count;
uint i;
uint8 cnt = 0;
for(i = last_winner; i < winners_count; i++) {
sendEth(tickets[getWinningNumber(i+3)], val);
cnt++;
if(cnt >= 9) {
last_winner = i;
return true;
}
}
last_winner = i;
if(cnt < 9) {
startNewDraw(lastbet_prize + msg.value);
} else {
sendEth(msg.sender, lastbet_prize + msg.value);
}
return true;
} else {
startNewDraw(lastbet_prize + msg.value);
}
return true;
}
/// new draw start
function startNewDraw(uint _msg_value) internal {
ticketsNum = 0;
startBlockNumber = block.number - 1;
endBlockNumber = startBlockNumber + liveBlocksNumber;
random_num += 1;
winners_count = 0;
last_winner = 0;
fee_balance = subZero(address(this).balance, _msg_value);
if(msg.value > 0) { sendEth(msg.sender, _msg_value); }
// fee_balance = address(this).balance;
if(autopayfee) { _payfee(); }
}
/// sending rewards to the investing, team and marketing contracts
function payfee() public {
require(fee_balance > 0);
uint val = fee_balance;
RNDInvestor rinv = RNDInvestor(inv_contract);
rinv.takeEther.value( percent(val, 25) )();
rtm_contract.transfer( percent(val, 74) );
fee_balance = 0;
emit PayFee(inv_contract, percent(val, 25) );
emit PayFee(rtm_contract, percent(val, 74) );
}
function _payfee() internal {
if(fee_balance <= 0) { return; }
uint val = fee_balance;
RNDInvestor rinv = RNDInvestor(inv_contract);
rinv.takeEther.value( percent(val, 25) )();
rtm_contract.transfer( percent(val, 74) );
fee_balance = 0;
emit PayFee(inv_contract, percent(val, 25) );
emit PayFee(rtm_contract, percent(val, 74) );
}
/// function for sending ETH with balance check (does not interrupt the program if balance is not sufficient)
function sendEth(address _to, uint _val) internal returns(bool) {
if(address(this).balance < _val) {
emit TransferError(_to, _val);
return false;
}
_to.transfer(_val);
emit Withdraw(address(this), _to, _val);
return true;
}
/// get winning ticket number basing on block hasg (block number is being calculated basing on specified displacement)
function getWinningNumber(uint _blockshift) internal constant returns (uint) {
return uint(blockhash(endBlockNumber - _blockshift)) % ticketsNum + 1;
}
/// current amount of jack pot 1
function jackPotA() public view returns (uint) {
return percent(prizeFund(), 10);
}
/// current amount of jack pot 2
function jackPotB() public view returns (uint) {
return percent(prizeFund(), 4);
}
/// current amount of jack pot 3
function jackPotC() public view returns (uint) {
return percent(prizeFund(), 1);
}
/// current amount of prize fund
function prizeFund() public view returns (uint) {
return ( (ticketsNum * onePotWei) / 100 ) * 90;
}
/// function for calculating definite percent of a number
function percent(uint _val, uint _percent) public pure returns (uint) {
return ( _val * _percent ) / 100;
}
/// returns owner address using ticket number
function getTicketOwner(uint _num) public view returns (address) {
if(ticketsNum == 0) {
return 0;
}
return tickets[_num];
}
/// returns amount of tickets for the current draw in the possession of specified address
function getTicketsCount(address _addr) public view returns (uint) {
if(ticketsNum == 0) {
return 0;
}
uint num = 0;
for(uint i = 0; i < ticketsNum; i++) {
if(tickets[i] == _addr) {
num++;
}
}
return num;
}
/// returns amount of tickets for the current draw in the possession of specified address
function balanceOf(address _addr) public view returns (uint) {
if(ticketsNum == 0) {
return 0;
}
uint num = 0;
for(uint i = 0; i < ticketsNum; i++) {
if(tickets[i] == _addr) {
num++;
}
}
return num;
}
/// returns tickets numbers for the current draw in the possession of specified address
function getTicketsAtAdress(address _address) public view returns(uint[]) {
uint[] memory result = new uint[](getTicketsCount(_address));
uint num = 0;
for(uint i = 0; i < ticketsNum; i++) {
if(tickets[i] == _address) {
result[num] = i;
num++;
}
}
return result;
}
/// returns amount of paid rewards for the current draw
function getLastWinner() public view returns(uint) {
return last_winner+1;
}
// /// investing contract address change
// function setInvContract(address _addr) onlyManager public {
// inv_contract = _addr;
// }
/// team contract address change
function setRtmContract(address _addr) onlyManager public {
rtm_contract = _addr;
}
function setAutoPayFee(bool _auto) onlyManager public {
autopayfee = _auto;
}
function contractBalance() public view returns (uint256) {
return address(this).balance;
}
function blockLeft() public view returns (uint256) {
if(endBlockNumber > block.number) {
return endBlockNumber - block.number;
}
return 0;
}
/// method for direct contract replenishment with ETH
function deposit() public payable {
require(msg.value > 0);
}
///Math functions
function safeMul(uint a, uint b) internal pure returns (uint) {
uint c = a * b;
require(a == 0 || c / a == b);
return c;
}
function safeSub(uint a, uint b) internal pure returns (uint) {
require(b <= a);
return a - b;
}
function subZero(uint a, uint b) internal pure returns (uint) {
if(a < b) {
return 0;
}
return a - b;
}
function safeAdd(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c>=a && c>=b);
return c;
}
function destroy() public onlyManager {
selfdestruct(manager);
}
}
/**
* @title Random Investor Contract
* @dev The Investor token contract
*/
contract RNDInvestor {
address public owner; // Token owner address
mapping (address => uint256) public balances; // balanceOf
address[] public addresses;
mapping (address => uint256) public debited;
mapping (address => mapping (address => uint256)) allowed;
string public standard = 'Random 1.1';
string public constant name = "Random Investor Token";
string public constant symbol = "RINVEST";
uint public constant decimals = 0;
uint public constant totalSupply = 2500;
uint public raised = 0;
uint public ownerPrice = 1 ether;
uint public soldAmount = 0; // current sold amount (for current state)
bool public buyAllowed = true;
bool public transferAllowed = false;
State public current_state; // current token state
// States
enum State {
Presale,
ICO,
Public
}
//
// Events
// This generates a publics event on the blockchain that will notify clients
event Sent(address from, address to, uint amount);
event Buy(address indexed sender, uint eth, uint fbt);
event Withdraw(address indexed sender, address to, uint eth);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
event Raised(uint _value);
event StateSwitch(State newState);
//
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
modifier onlyIfAllowed() {
if(!transferAllowed) { require(msg.sender == owner); }
_;
}
//
// Functions
//
// Constructor
function RNDInvestor() public {
owner = msg.sender;
balances[owner] = totalSupply;
}
// fallback function
function() payable public {
if(current_state == State.Public) {
takeEther();
return;
}
require(buyAllowed);
require(msg.value >= ownerPrice);
require(msg.sender != owner);
uint wei_value = msg.value;
// uint tokens = safeMul(wei_value, ownerPrice);
uint tokens = wei_value / ownerPrice;
uint cost = tokens * ownerPrice;
if(current_state == State.Presale) {
tokens = tokens * 2;
}
uint currentSoldAmount = safeAdd(tokens, soldAmount);
if (current_state == State.Presale) {
require(currentSoldAmount <= 1000);
}
require(balances[owner] >= tokens);
balances[owner] = safeSub(balances[owner], tokens);
balances[msg.sender] = safeAdd(balances[msg.sender], tokens);
soldAmount = safeAdd(soldAmount, tokens);
uint extra_ether = safeSub(msg.value, cost);
if(extra_ether > 0) {
msg.sender.transfer(extra_ether);
}
}
function takeEther() payable public {
if(msg.value > 0) {
raised += msg.value;
emit Raised(msg.value);
} else {
withdraw();
}
}
function setOwnerPrice(uint _newPrice) public
onlyOwner
returns (bool success)
{
ownerPrice = _newPrice;
return true;
}
function setTokenState(State _nextState) public
onlyOwner
returns (bool success)
{
bool canSwitchState
= (current_state == State.Presale && _nextState == State.ICO)
|| (current_state == State.Presale && _nextState == State.Public)
|| (current_state == State.ICO && _nextState == State.Public) ;
require(canSwitchState);
current_state = _nextState;
emit StateSwitch(_nextState);
return true;
}
function setBuyAllowed(bool _allowed) public
onlyOwner
returns (bool success)
{
buyAllowed = _allowed;
return true;
}
function allowTransfer() public
onlyOwner
returns (bool success)
{
transferAllowed = true;
return true;
}
/**
* @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 {
if (newOwner != address(0)) {
owner = newOwner;
}
}
function safeMul(uint a, uint b) internal pure returns (uint) {
uint c = a * b;
require(a == 0 || c / a == b);
return c;
}
function safeSub(uint a, uint b) internal pure returns (uint) {
require(b <= a);
return a - b;
}
function safeAdd(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c>=a && c>=b);
return c;
}
function withdraw() public returns (bool success) {
uint val = ethBalanceOf(msg.sender);
if(val > 0) {
msg.sender.transfer(val);
debited[msg.sender] += val;
return true;
}
return false;
}
function ethBalanceOf(address _investor) public view returns (uint256 balance) {
uint val = (raised / totalSupply) * balances[_investor];
if(val >= debited[_investor]) {
return val - debited[_investor];
}
return 0;
}
function manager_withdraw() onlyOwner public {
uint summ = 0;
for(uint i = 0; i < addresses.length; i++) {
summ += ethBalanceOf(addresses[i]);
}
require(summ < address(this).balance);
msg.sender.transfer(address(this).balance - summ);
}
function manual_withdraw() public {
for(uint i = 0; i < addresses.length; i++) {
addresses[i].transfer( ethBalanceOf(addresses[i]) );
}
}
function checkAddress(address _addr) public
returns (bool have_addr)
{
for(uint i=0; i<addresses.length; i++) {
if(addresses[i] == _addr) {
return true;
}
}
addresses.push(_addr);
return true;
}
function destroy() public onlyOwner {
selfdestruct(owner);
}
/**
* ERC 20 token functions
*
* https://github.com/ethereum/EIPs/issues/20
*/
function transfer(address _to, uint256 _value) public
onlyIfAllowed
returns (bool success)
{
if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
checkAddress(_to);
return true;
} else { return false; }
}
function transferFrom(address _from, address _to, uint256 _value) public
onlyIfAllowed
returns (bool success)
{
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
checkAddress(_to);
return true;
} else { return false; }
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public
returns (bool success)
{
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public
constant returns (uint256 remaining)
{
return allowed[_owner][_spender];
}
}
{
"compilationTarget": {
"Random.sol": "Random"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"jackPotB","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rtm_contract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fee_balance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"jackPotA","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_val","type":"uint256"},{"name":"_percent","type":"uint256"}],"name":"percent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"startBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"getTicketsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liveBlocksNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"}],"name":"setRtmContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"others_prize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"onePotWei","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"inv_contract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"last_winner","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"contractBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockLeft","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"autopayfee","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_ticketNum","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_num","type":"uint256"}],"name":"getTicketOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"jackPotC","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"EndLottery","outputs":[{"name":"success","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"endBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"manager_withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ticketsNum","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"payfee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"random_num","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_auto","type":"bool"}],"name":"setAutoPayFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"prizeFund","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_address","type":"address"}],"name":"getTicketsAtAdress","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLastWinner","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"winners_count","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":"sender","type":"address"},{"indexed":false,"name":"eth","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"eth","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"TransferError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"PayFee","type":"event"}]