Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.5.8;
- pragma experimental ABIEncoderV2;
- library SafeMath {
- /**
- * @dev Returns the lowest value of the two integers
- */
- function min(uint256 a, uint256 b) internal pure returns (uint256) {
- return a < b ? a : b;
- }
- /**
- * @dev Multiplies two numbers, throws on overflow.
- */
- 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;
- }
- /**
- * @dev Integer division of two numbers, truncating the quotient.
- */
- 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;
- }
- /**
- * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
- */
- function sub(uint256 a, uint256 b) internal pure returns (uint256) {
- assert(b <= a);
- return a - b;
- }
- /**
- * @dev Adds two numbers, throws on overflow.
- */
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- assert(c >= a);
- return c;
- }
- function percentageOf(uint256 total, uint256 percentage) internal pure returns (uint256) {
- return div(mul(total, percentage), 100);
- }
- function getPercentage(uint256 total, uint256 piece) internal pure returns (uint256) {
- return div(piece, total);
- }
- }
- contract Protected {
- bool public active = false;
- address payable public ceoAddress;
- mapping (address => bool) public admin;
- function isAdmin (address _adr) public view returns (bool) {
- return admin[_adr];
- }
- function addAdmin (address _adr) external adminOnly {
- admin[_adr] = true;
- }
- function removeAdmin (address _adr) external adminOnly {
- require(_adr != msg.sender, "Action not allowed");
- admin[_adr] = false;
- }
- modifier adminOnly () {
- require(admin[msg.sender] == true, "Unauthorized");
- _;
- }
- modifier activeOnly () {
- require(active == true, "Inactive");
- _;
- }
- constructor () public {
- ceoAddress = msg.sender;
- admin[msg.sender] = true;
- }
- function toggleActive () external adminOnly returns (bool) {
- active = !active;
- return active;
- }
- function getCEOAddress () public view returns (address payable) {
- return ceoAddress;
- }
- }
- contract Moon is Protected {
- // ----------------------- Unit System
- struct Unit {
- string name;
- uint256 cookies_per_second;
- uint256 starting_price;
- uint256 price_inc;
- uint256 shares;
- uint256 buy_fee;
- uint256 sell_fee;
- bool unlocked;
- }
- mapping (uint256 => Unit) private units;
- mapping (uint256 => uint256) private unit_price;
- uint256 private total_units;
- // Dividend System
- mapping (address => uint256) public last_withdraw; // Should probably rename to something that reflects "last withdraw/unclaimed update"
- mapping (address => uint256) public shares;
- mapping (address => uint256) public unclaimed;
- // Dividend System
- uint256 public pot = 0; // We'll get back to this later
- uint256 public legacy_pot = 0;
- uint256 public total_shares = 0;
- uint256 private precision_multiplier = 1000000;
- // Buying
- address payable private dev;
- address payable private dev2;
- address payable private dev3;
- uint256 private dfp = 2;
- uint256 private dfp3 = 1;
- uint256 private rfp = 5;
- // --------------------- Unit Data System
- mapping (uint256 => mapping (address => uint256)) private unit;
- mapping (uint256 => uint256) private unit_count;
- mapping (address => uint256) private cookies;
- mapping (address => uint256) private production_start;
- uint256 public total_produced_cookies = 0;
- uint256 public total_sold_cookies = 0;
- uint256 public last_update = 0;
- // Dividend System
- event Withdraw (address user, uint256 value, uint256 timestamp);
- event Deposit (address user, uint256 value, uint256 bought_shares, uint256 timestamp);
- event Remove (address user, uint256 sold_shares, uint256 timestamp);
- // -------------------- Dividend System
- function update (address user) internal {
- // Update share related stuff
- unclaimed[user] = SafeMath.add(unclaimed[user], calculateGains(user));
- last_withdraw[user] = legacy_pot;
- // Update cookie production stuff
- cookies[user] = SafeMath.add(cookies[user], getProducedCookiesForPlayer(user));
- production_start[user] = now;
- // Tracking max cookies
- total_produced_cookies = SafeMath.add(total_produced_cookies, calculateProducedCookiesSinceLastUpdate());
- last_update = now;
- }
- function getTotalUnits () public view returns (uint256) {
- return total_units;
- }
- function calculateProducedCookiesSinceLastUpdate() internal view returns (uint256) {
- uint256 cps = 0;
- uint256 total_unit_count = getTotalUnits();
- for (uint8 i = 0; i < total_unit_count; i++) {
- if (unit_count[i] > 0) {
- uint256 cookies_per_second = getUnitCookiesPerSecond(i);
- uint256 total_cookies_per_second = SafeMath.mul(cookies_per_second, unit_count[i]);
- cps = SafeMath.add(cps, total_cookies_per_second);
- }
- }
- uint256 produced_time = SafeMath.sub(now, last_update);
- uint256 produced = SafeMath.mul(cps, produced_time);
- return produced;
- }
- function getTotalProducedCookies() internal view returns (uint256) {
- return SafeMath.add(total_produced_cookies, calculateProducedCookiesSinceLastUpdate());
- }
- function getTotalCookiesInExistence() internal view returns (uint256) {
- return SafeMath.sub(getTotalProducedCookies(), total_sold_cookies);
- }
- function calculateGains (address user) public view returns (uint256) {
- uint256 available_pot = SafeMath.sub(legacy_pot, last_withdraw[user]);
- if (available_pot == 0 || shares[user] == 0) {
- return 0;
- }
- uint256 p_in_m = SafeMath.div(SafeMath.mul(shares[user], precision_multiplier), total_shares);
- uint256 gains = SafeMath.div(SafeMath.mul(p_in_m, available_pot), precision_multiplier);
- return gains;
- }
- function depositSharesForPlayer (address player, uint256 value, uint256 bought_shares) internal {
- require (value > 0, "Invalid amount");
- require (bought_shares > 0, "Invalid amount of shares");
- // Ensure previous gains are calculated and stored
- update(player);
- // Is this where the user buys shares?
- // uint256 share_value = 1000000; // Needs to be calculated somehow unless we follow a different system for this. Maybe each unit gives X shares?
- // uint256 bought_shares = SafeMath.div(SafeMath.div(SafeMath.mul(msg.value, precision_multiplier), share_value), precision_multiplier); // This should return the shares based on a share price, but I think we need to adjust this to something else related to the cookies/unit prices
- pot = SafeMath.add(pot, value);
- legacy_pot = SafeMath.add(legacy_pot, value);
- total_shares = SafeMath.add(total_shares, bought_shares);
- shares[player] = SafeMath.add(shares[player], bought_shares);
- emit Deposit(player, value, bought_shares, now);
- }
- function removeSharesForPlayer (address player, uint256 sold_shares) private {
- require (sold_shares > 0, "Invalid amount of shares");
- // Ensure previous gains are calculated and stored
- update(player);
- total_shares = SafeMath.sub(total_shares, sold_shares);
- shares[player] = SafeMath.sub(shares[player], sold_shares);
- emit Remove(player, sold_shares, now);
- }
- function withdrawGains () public {
- // Calculate total gains (previously unclaimed + gains since last calculation)
- uint256 total_gains = SafeMath.add(unclaimed[msg.sender], calculateGains(msg.sender));
- // Ensure there are funds to withdraw
- assert (total_gains > 0);
- assert (pot > total_gains);
- // Withdraw from dividend pot
- pot = SafeMath.sub(pot, total_gains);
- // Reset user stats to reflect a withdrawal
- unclaimed[msg.sender] = 0;
- last_withdraw[msg.sender] = legacy_pot;
- // Transfer funds
- msg.sender.transfer(total_gains);
- emit Withdraw(msg.sender, total_gains, now);
- }
- function getUnitPrice(uint256 unit_id) public view returns (uint256) {
- if (unit_price[unit_id] == 0) {
- return units[unit_id].starting_price;
- }
- return unit_price[unit_id];
- }
- function getUnitPriceInc(uint256 unit_id) public view returns (uint256) {
- return units[unit_id].price_inc;
- }
- function getUnitBuyFee(uint256 unit_id) public view returns (uint256) {
- return units[unit_id].buy_fee;
- }
- function getUnitSellFee(uint256 unit_id) public view returns (uint256) {
- return units[unit_id].sell_fee;
- }
- function getUnitCookiesPerSecond(uint256 unit_id) public view returns (uint256) {
- return units[unit_id].cookies_per_second;
- }
- function getUnitShares(uint256 unit_id) public view returns (uint256) {
- return units[unit_id].shares;
- }
- function setUnitPrice(uint256 unit_id, uint256 _unit_price) internal {
- unit_price[unit_id] = _unit_price;
- }
- function getUnit(uint256 unit_id) public view returns (Unit memory) {
- require (unit_id >= 0, 'Invalid unit_id');
- require (unit_id < total_units, 'This unit does not exist');
- return units[unit_id];
- }
- function addUnit(
- string calldata name,
- uint256 cookies_per_second,
- uint256 starting_price,
- uint256 price_inc,
- uint256 shares_per_unit,
- uint256 buy_fee,
- uint256 sell_fee,
- bool unlocked
- ) external adminOnly returns (Unit memory) {
- // Create Unit
- units[total_units] = Unit({
- name:name,
- cookies_per_second:cookies_per_second,
- starting_price:starting_price,
- price_inc:price_inc,
- shares:shares_per_unit,
- buy_fee:buy_fee,
- sell_fee:sell_fee,
- unlocked:unlocked
- });
- // Update total units
- total_units = SafeMath.add(total_units, 1);
- // Return the added unit
- return units[total_units];
- }
- function toggleUnit(uint256 unit_id) public adminOnly returns (bool) {
- require (unit_id >= 0, 'Invalid unit_id');
- require (unit_id < total_units, 'This unit does not exist');
- units[unit_id].unlocked = !units[unit_id].unlocked;
- return true;
- }
- // -------------------- Banking System
- uint256 private cookie_pot;
- mapping (uint256 => uint256) private unit_pot;
- function getUnitPot (uint256 unit_id) public view returns (uint256) {
- return unit_pot[unit_id];
- }
- function getCookiePot () public view returns (uint256) {
- return cookie_pot;
- }
- // function getTotalFunds () public view returns (uint256) {
- // uint256 total_unit_count = getTotalUnits();
- // uint256 total_funds = cookie_pot;
- // for (uint8 i = 0; i < total_unit_count; i++) {
- // total_funds = SafeMath.add(total_funds, getUnitPot(i));
- // }
- // return total_funds;
- // }
- function depositToCookiePot (uint256 value) private returns (bool) {
- require(value > 0, "Invalid amount");
- cookie_pot = SafeMath.add(cookie_pot, value);
- return true;
- }
- function depositToUnitPot (uint256 unit_id, uint256 value) private returns (bool) {
- require(value > 0, "Invalid amount");
- unit_pot[unit_id] = SafeMath.add(unit_pot[unit_id], value);
- return true;
- }
- function withdrawFromCookiePot (address payable _to, uint256 amount) external adminOnly returns (bool) {
- require (amount > 0, "Invalid amount");
- require (amount <= getCookiePot(), "Insufficient funds");
- cookie_pot = SafeMath.sub(cookie_pot, amount);
- _to.transfer(amount);
- return true;
- }
- function withdrawFromUnitPot (address payable _to, uint256 unit_id, uint256 amount) internal returns (bool) {
- require (amount > 0, "Invalid amount");
- require (amount <= getUnitPot(unit_id), "Insufficient funds");
- unit_pot[unit_id] = SafeMath.sub(unit_pot[unit_id], amount);
- _to.transfer(amount);
- return true;
- }
- // function withdraw (uint256 amount) external adminOnly returns (bool) {
- // require (amount <= getTotalFunds(), "Insufficient funds"); // Need to change this to frag
- // msg.sender.transfer(amount);
- // return true;
- // }
- function getUnitsForPlayer(uint256 unit_id, address player) public view returns (uint256) {
- return unit[unit_id][player];
- }
- function getTotalUnitCount(uint256 unit_id) public view returns (uint256) {
- return unit_count[unit_id];
- }
- function getProductionStartForPlayer(address player) public view returns (uint256) {
- return production_start[player];
- }
- function setTotalUnitCount(uint256 unit_id, uint256 count) internal {
- require (count >= 0, 'Invalid count');
- unit_count[unit_id] = count;
- }
- function setUnitsForPlayer(uint256 unit_id, address player, uint256 value) internal {
- require (value >= 0, "Invalid value");
- unit[unit_id][player] = value;
- assert (unit[unit_id][player] == value);
- }
- function getProducedCookiesForPlayer(address player) public view returns (uint256) {
- uint256 production_from = getProductionStartForPlayer(player);
- if (production_from == 0) {
- return 0;
- }
- uint256 total_unit_count = getTotalUnits();
- uint256 produced_time = SafeMath.sub(now, production_from);
- uint256 produced = 0;
- for (uint8 i = 0; i < total_unit_count; i++) {
- if (unit[i][player] > 0) {
- uint256 cookies_per_second = getUnitCookiesPerSecond(i);
- uint256 produced_cookies = SafeMath.mul(cookies_per_second, produced_time);
- produced = SafeMath.add(produced, produced_cookies);
- }
- }
- return produced;
- }
- function getCookiesForPlayer(address player) public view returns (uint256) {
- uint256 cookies_on_hand = cookies[player];
- uint256 produced_cookies = getProducedCookiesForPlayer(player);
- // Add produced cookies
- uint256 total_cookies = SafeMath.add(cookies_on_hand, produced_cookies);
- return total_cookies;
- }
- function setCookiesForPlayer(address player, uint256 value) internal {
- require (value >= 0, "Invalid value");
- cookies[player] = value;
- assert (cookies[player] == value);
- }
- // -------------------- Buying System
- constructor (address payable _dev2, address payable _dev3) Protected() public {
- dev = msg.sender;
- dev2 = _dev2;
- dev3 = _dev3;
- }
- function calculateBoughtUnits(uint256 unit_id, uint256 value) public view returns (uint256) {
- return SafeMath.div(value, getUnitPrice(unit_id));
- }
- function calculateNewUnitPric (uint256 unit_id, uint256 value) public view returns (uint256) {
- return SafeMath.add(SafeMath.mul(calculateBoughtUnits(unit_id, value), getUnitPriceInc(unit_id)), getUnitPrice(unit_id));
- }
- function calculateNewPlayerUnits(uint256 unit_id, uint256 value, address player) public view returns (uint256) {
- return SafeMath.add(calculateBoughtUnits(unit_id, value), getUnitsForPlayer(unit_id, player));
- }
- function calculateSharesBought(uint256 unit_id, uint256 value) public view returns (uint256) {
- return SafeMath.mul(calculateBoughtUnits(unit_id, value), getUnitShares(unit_id));
- }
- function calculateTotalFees(uint256 unit_id, uint256 value) public view returns (uint256) {
- uint256 dev_fee = SafeMath.percentageOf(value, dfp);
- uint256 dev_fee3 = SafeMath.percentageOf(value, dfp3);
- uint256 ref_fee = SafeMath.percentageOf(value, rfp);
- uint256 for_cookie_and_unit_divs = SafeMath.percentageOf(value, getUnitBuyFee(unit_id));
- return SafeMath.add(
- SafeMath.add(dev_fee, dev_fee),
- SafeMath.add(
- SafeMath.add(dev_fee3, ref_fee),
- for_cookie_and_unit_divs
- ));
- }
- function calculateForUnitPot(uint256 unit_id, uint256 value) public view returns (uint256) {
- uint256 total_fees = calculateTotalFees(unit_id, value);
- return SafeMath.sub(value, total_fees);
- }
- function handleBuyUnits (address player, uint256 value, uint256 unit_id, uint256 for_shares) internal {
- uint256 bought_units = SafeMath.div(value, getUnitPrice(unit_id));
- uint256 new_unit_price = SafeMath.add(SafeMath.mul(bought_units, getUnitPriceInc(unit_id)), getUnitPrice(unit_id));
- uint256 player_units = SafeMath.add(bought_units, getUnitsForPlayer(unit_id, player));
- uint256 shares_bought = SafeMath.mul(bought_units, getUnitShares(unit_id));
- uint256 new_unit_count = SafeMath.add(getTotalUnitCount(unit_id), bought_units);
- depositSharesForPlayer(player, for_shares, shares_bought);
- setUnitPrice(unit_id, new_unit_price);
- setTotalUnitCount(unit_id, new_unit_count);
- setUnitsForPlayer(unit_id, player, player_units);
- }
- /*
- * This function should do the following:
- * Increase player shares based on how many unit X the user buys
- * Distribute dev fees
- * Distribute
- *
- */
- function buyUnits (uint256 unit_id, address payable ref) external payable returns (bool) {
- // Make all monetary calculations
- uint256 dev_fee = SafeMath.percentageOf(msg.value, dfp);
- uint256 dev_fee3 = SafeMath.percentageOf(msg.value, dfp3);
- uint256 ref_fee = SafeMath.percentageOf(msg.value, rfp);
- uint256 for_cookie_and_unit_divs = SafeMath.percentageOf(msg.value, getUnitBuyFee(unit_id));
- uint256 total_fees = SafeMath.add(
- SafeMath.add(dev_fee, dev_fee),
- SafeMath.add(
- SafeMath.add(dev_fee3, ref_fee),
- for_cookie_and_unit_divs
- ));
- uint256 for_pots = SafeMath.div(for_cookie_and_unit_divs, 2);
- uint256 for_unit_pot = SafeMath.sub(msg.value, total_fees);
- // Distribute funds
- dev.transfer(dev_fee);
- dev2.transfer(dev_fee);
- dev3.transfer(dev_fee3);
- ref.transfer(ref_fee);
- handleBuyUnits(msg.sender, msg.value, unit_id, for_pots);
- depositToCookiePot(for_pots);
- depositToUnitPot(unit_id, for_unit_pot);
- return true;
- }
- function calculateSellPricePerUnitWithFees(uint256 unit_id) public view returns (uint256) {
- return SafeMath.div(getUnitPot(unit_id), getTotalUnitCount(unit_id));
- }
- function calculateUnitSellValueWithFees(address payable player, uint256 unit_id) public view returns (uint256) {
- uint256 units_count = getUnitsForPlayer(unit_id, player);
- uint256 price_per_unit = calculateSellPricePerUnitWithFees(unit_id);
- return SafeMath.mul(units_count, price_per_unit);
- }
- function handleSellUnits (address player, uint256 unit_id) internal {
- uint256 sold_units = getUnitsForPlayer(unit_id, player);
- uint256 sold_shares = SafeMath.mul(sold_units, getUnitShares(unit_id));
- uint256 new_unit_price = SafeMath.sub(SafeMath.mul(sold_units, getUnitPriceInc(unit_id)), getUnitPrice(unit_id));
- uint256 new_unit_count = SafeMath.sub(getTotalUnitCount(unit_id), sold_units);
- removeSharesForPlayer(player, sold_shares);
- setUnitPrice(unit_id, new_unit_price);
- setTotalUnitCount(unit_id, new_unit_count);
- setUnitsForPlayer(unit_id, player, 0);
- }
- /*
- * This function should do the following:
- * It should stop the cookie production where it is
- * It should distribute dev fees
- * It should update & distribute shares
- */
- function sellUnits (uint256 unit_id, address payable ref) external returns (bool) {
- // Make all monetary calculations
- uint256 value = calculateUnitSellValueWithFees(msg.sender, unit_id);
- uint256 dev_fee = SafeMath.percentageOf(value, dfp);
- uint256 dev_fee3 = SafeMath.percentageOf(value, dfp3);
- uint256 ref_fee = SafeMath.percentageOf(value, rfp);
- uint256 for_cookie_and_unit_divs = SafeMath.percentageOf(value, getUnitSellFee(unit_id));
- uint256 for_cookie_pot = SafeMath.div(for_cookie_and_unit_divs, 2);
- uint256 total_fees = SafeMath.add(
- SafeMath.add(dev_fee, dev_fee),
- SafeMath.add(
- SafeMath.add(dev_fee3, ref_fee),
- for_cookie_and_unit_divs
- ));
- uint256 value_dist = SafeMath.sub(value, total_fees);
- // Distribute funds
- dev.transfer(dev_fee);
- dev2.transfer(dev_fee);
- dev3.transfer(dev_fee3);
- ref.transfer(ref_fee);
- handleSellUnits(msg.sender, unit_id);
- depositToCookiePot(for_cookie_pot);
- withdrawFromUnitPot(msg.sender, unit_id, value_dist);
- return true;
- }
- function calculateCookieValue (uint256 cookie_count) public view returns (uint256) {
- if (cookie_count == 0) {
- return 0;
- }
- uint256 total_cookies_in_existence = getTotalCookiesInExistence();
- uint256 available_pot = SafeMath.percentageOf(cookie_pot, 10);
- uint256 cookie_p = SafeMath.div(SafeMath.mul(precision_multiplier, cookie_count), total_cookies_in_existence);
- uint256 p_value = SafeMath.mul(available_pot, cookie_p);
- uint256 value = SafeMath.div(p_value, precision_multiplier);
- if (value > cookie_pot) {
- return cookie_pot;
- }
- return value;
- }
- function calculateCookieValueForPlayer() public view returns (uint256) {
- return calculateCookieValue(getCookiesForPlayer(msg.sender));
- }
- function sellCookies() external returns (bool) {
- uint256 produced_cookies = getCookiesForPlayer(msg.sender);
- uint256 cookie_value = calculateCookieValue(produced_cookies);
- assert(cookie_value > 0);
- cookies[msg.sender] = 0;
- production_start[msg.sender] = now;
- cookie_pot = SafeMath.sub(cookie_pot, cookie_value);
- total_sold_cookies = SafeMath.add(total_sold_cookies, produced_cookies);
- msg.sender.transfer(cookie_value);
- return true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement