Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

pragma solidity ^0.4.11;

//Глобальные переменные:

contract PreMasterNode {

  // Владелец контракта

  address public owner;

  // Работник для ручного расчета вознаграждений

  address public worker;

  // start: status = true;

  // stop : status = false;

  // Работает контракт или нет

  bool public status = false;

  // Объем Зефира на ноду

  uint public constant etzPerNode = 20000 * 10 ** 18;

  // Вознаграждение местернод за блок

  uint public constant rewardPerBlock = 1 * 10 ** 18;

  // Количество мастренод

  uint nodeCount = 0;

  // Адреса, работающие с контрактом

  address[] entries;

  // Номер блока на котором были распределены награды последний раз

  uint public blockOrigin;

  // Номер блока на котором контракт был запущен

  uint public blockStart;

  // Номер блока, на котором контракт был установлен

  uint public blockStop;

  // Баланс владельца

  uint public ownerBalance = 0;

  // Общая распределенная награда

  uint public accBlockReward;

  // Set manualwork = true when entries. length > 300

  // Флаг ручной обработки наград - рекомендуется установить, когда количество юзеров будет больше 300

  bool public manualWork = false;

  // manualwork state

  uint public pendingPerNodeReward = 0;  // Ожидаемая награда за блок для ручного распределения

  uint32 public pendingEntriesStart = 0;  // Индекс первого аккаунта распределения наград

НЕ нашли? Не то? Что вы ищете?

  uint32 public pendingEntriesEnd = 0;  // Индекс последнего аккаунта распределения наград

  // Описание юзера

  struct user {

  // Флаг регистрации

  bool registered;

  // Сколько у него нод

  uint nodes;

  // Полученная награда юзера

  uint blockReward;

  // Баланс

  uint balance;

  }

  // Пользователи контракта

  mapping(address => user) users;

  // Логирование вывода средств и перевода 

  // event

  event userWithdraw(address addr, uint amount);

  event userCharge(address addr, uint amount, uint newBalance);

  // Модификатор - только для владельца

  modifier onlyOwner() {

  if (msg. sender!= owner)

  {

  revert();

  }

  _;

  }

  // Модификатор - только для работника

  modifier onlyWorker() {

  if (msg. sender!= owner || msg. sender!= worker)

  {

  revert();

  }

  _;

  }

  // Создание контракта - первичная установка владельца и работника

  function PreMasterNode() public {

  owner = msg. sender;

  worker = msg. sender;

  }

  // Получить количество нод

  function getNodeCount() constant public returns (uint) {

  return nodeCount;

  }

  // Установка нового владельца

  function setOwner(address newOwner) onlyOwner public returns (address) {

  owner = newOwner;

  return owner;

  }

  // Установка нового работника

  function setWorker(address newWorker) onlyOwner public returns (address) {

  worker = newWorker;

  return worker;

  }

  // Остановка контракта - доступна только если контракт работает, при остановке считаются награды за блок

  function stop() onlyOwner public {

  require(status);

  autoRewards();

  blockStop = block. number;

  status = false;

  }

  // Сменить тип работы контракта - с ручного на автомат и обратно

  function switchWorkMode() onlyOwner public {

  manualWork = !manualWork;

  }

  // Запуск контракта - доступна только если контракт не работает

  function start() onlyOwner public {

  require(!status);

  blockOrigin = block. number;

  blockStart = blockOrigin;

  blockStop = 0;

  status = true;

  }

  function releasedRewards() constant public returns (uint) {

  if (manualWork) return accBlockReward;

  else return calcReward() + accBlockReward;

  }

  // Получить количество адресов пользователей

  function getEntriesLength() constant public returns (uint) {

  return entries. length;

  }

  // Получить информацию о пользователе. Возвращает флаг регистрации, количество нод, награду и баланс. Если выключена ручная обработка наград, еще предсказывает награду.

  function getMyInfo(address addr) public constant returns (bool reg, uint myNodes, uint myReward, uint myBalance) {

  user storage u = users[addr];

  if (nodeCount > 0 && !manualWork) {

  myReward = u. blockReward + ((calcReward() / nodeCount) * u. nodes);

  if (myReward > address(this).balance) {

  myReward = address(this).balance;

  }

  } else {

  myReward = u. blockReward;

  }

  myBalance = u. balance;

  myNodes = u. nodes;

  reg = u. registered;

  }

  // Ручное распределение наград. Доступна только Работнику

  // Не срабатывает если: 1. Баланс Владельца = 0

  //  2. Выключена обработка вручную

  //  4. Количество нод = 0

  //

  // Работает в 2 этапа:

  // 1. Рассчитывает награду. Определяет награду на ноду. Инициализирует набор аккаунтов для распределения наград (от нуля до последнего аккаунта).

  // 2. Пачками по 100 штук накидывает аккаунтам награду, списывает ее со счета Владельца и добавляет ее в общий распределенный пул, если она может быть списана со счета Владельца.

  function manualRewards() public onlyWorker returns (bool) {

  require(ownerBalance > 0 && manualWork && nodeCount > 0);

  uint32 gap = pendingEntriesEnd - pendingEntriesStart;

  if (gap == 0) {

  uint allReward = calcReward();

  blockOrigin = block. number;

  pendingPerNodeReward = allReward / nodeCount;

  pendingEntriesStart = 0;

  pendingEntriesEnd = uint32(entries. length);

  } else if (gap > 0) {

  uint32 begin = pendingEntriesStart;

  uint32 end = pendingEntriesEnd;

  if (gap > 100) {

  end = begin + 100;

  pendingEntriesStart = end;

  } else {

  pendingEntriesStart = pendingEntriesEnd;

  }

  for (uint32 i = begin; i < end; i++) {

  user storage u = users[entries[i]];

  uint myReward = pendingPerNodeReward * u. nodes;

  if (myReward > 0 && ownerBalance >= myReward)

  {

  ownerBalance -= myReward;

  accBlockReward += myReward;

  u. blockReward += myReward;

  }

  }

  }

  return true;

  }

  // Автоматическое распределение наград

  // Не срабатывает если: 1. Баланс Владельца = 0

  //  2. Включена обработка вручную

  //  3. Контракт выключен

  //  4. Количество нод = 0

  // Рассчитывается награда. Эта награда вычитается из баланса Владельца и прибавляется к количеству общей распределенной награды.

  // Рассчитывается награда на ноду. Сохраняется последний блок расчета наград. Общая награда делится между нодами юзеров.

  function autoRewards() private returns (bool) {

  if (ownerBalance == 0 || manualWork || !status || nodeCount == 0) return false;

  uint allReward = calcReward();

  ownerBalance -= allReward;

  accBlockReward += allReward;

  uint perNodeReward = allReward / nodeCount;

  blockOrigin = block. number;

  uint32 length = uint32(entries. length);

  for (uint32 i = 0; i < length; i++) {

  user storage u = users[entries[i]];

  if (u. nodes > 0)

  {

  u. blockReward += perNodeReward * u. nodes;

  }

  }

  return true;

  }

  // Получить баланс контракта

  function getContractBalance() public constant returns (uint) {

  return address(this).balance;

  }

  // Расчет наград

  // Рассчитывается количество блоков с момента последнего подсчета. Если контракт был остановлен (поведение если не был запущен не понятно) - награда = 0

  // Если контракт запущен и были блоки с последнего подсчета, и их количество меньше 5 000 000 и есть ноды, то наградой считается количество блоков, умноженное на награду за блок

  // Если эта награда превышает баланс Владельца - то наградой считается баланс владельца

  function calcReward() constant internal returns (uint) {

  uint blockGap;

  if (blockStop > 0 && blockOrigin < blockStop) {

  blockGap = blockStop - blockOrigin;

  } else if (blockStop > 0) {

  blockGap = 0;

  } else {

  blockGap = block. number - blockOrigin;

  }

  if (status && blockGap > 0 && blockGap < 5000000 && nodeCount > 0) {

  uint reward = blockGap * rewardPerBlock;

  if (reward > ownerBalance) {

  return ownerBalance;

  } else {

  return reward;

  }

  }

  return 0;

  }

  // Зачисление зефира на контракт. 3 режима работы:

  // А) Если плательщик = Вдаделец:

  // Если перевод не нулевой - пополняется счет Владельца на эту сумму

  // Иначе если номер блока больше 8 000 000, то в случае, когда контракт отключен, Владельцу возвращается его баланс с баланса контракта

  // Иначе в случае выключенного контракта и наличия денег на счете Владельца, если баланс контракта меньше баланса Владельца, то с контракта выводится все деньги и размер счета Владельца уменьшается на эту сумму

  // Если баланс контракта больше либо равен балансу Владельца, то с контракта выводится объем счета владельца и счет обнуляется

  // Б) Если не Владелец и перевод нулевой

  // Если есть ноды - автосчитаем награды. Объем для вывода = баланс пользователя + награда пользователя (если он больше баланса контракта, то объем для вывода уменьшается на баланс контракта)

  // Уменьшаем общий объем нод на ноды юзера. Обнуляем юзера. И переводим ему объем для вывода с баланса контракта. Логируем, что юзер вывел такой-то объем денег

  // В) Если не Владелец и перевод не нулевой

  // Считаем сколько нод было у юзера согласно его балансу, считаем сколько будет нод у юзера, при новом балансе

  // Если юзер не зарегистрирован и текущее количество его нод > 0, то ставим флаг регистрации

  // Если количество нод увеличилось, то:

  // 1. если раньше не было нод, будем считать награды с этого блока, иначе считаем награды

  // 2. увеличиваем общее количество нод на новые ноды юзера и сохраняем новое количество нод юзера

  // Обновляем баланс юзера и логируем юзера, сколько он перевел и его общий баланс

  function() payable public {

  user storage u = users[msg. sender];

  if (msg. sender == owner) {

  if (msg. value > 0) {

  ownerBalance += msg. value;

  } else if (block. number > 8000000) {

  require(!status);

  owner. transfer(ownerBalance);

  } else {

  require(!status && ownerBalance > 0);

  uint maxBalance = address(this).balance;

  if (maxBalance < ownerBalance) {

  owner. transfer(maxBalance);

  ownerBalance -= maxBalance;

  } else {

  owner. transfer(ownerBalance);

  ownerBalance = 0;

  }

  }

  } else if (msg. value == 0 && u. balance > 0 && nodeCount >= u. nodes) {

  if (u. nodes > 0) {

  autoRewards();

  }

  uint amount = u. balance + u. blockReward;

  if (address(this).balance < amount) {

  amount = address(this).balance;

  }

  // Set rewards

  nodeCount -= u. nodes;

  // Reset user data

  u. nodes = 0;

  u. balance = 0;

  u. blockReward = 0;

  // transfer

  msg. sender. transfer(amount);

  emit userWithdraw(msg. sender, amount);

  } else if (msg. value > 0) {

  uint orginNodes = u. balance / etzPerNode;

  uint currentNodes = (u. balance + msg. value) / etzPerNode;

  if (!u. registered && currentNodes > 0) {

  u. registered = true;

  entries. push(msg. sender);

  }

  if (currentNodes > orginNodes) {

  if (nodeCount == 0) {

  blockOrigin = block. number;

  } else {

  autoRewards();

  }

  nodeCount += (currentNodes - orginNodes);

  u. nodes = currentNodes;

  }

  u. balance += msg. value;

  emit userCharge(msg. sender, msg. value, u. balance);

  }

  }

  // Возвращает список адресов юзеров. Возвращает общее количество и первые 20 адресов с номера, который был передан в параметрах

  function getAddresses(uint startPos) public constant returns (uint length, address[20] data) {

  length = uint(entries. length);

  for (uint i = 0; i < 20 && (i + startPos) < length; i++) {

  data[i] = entries[i + startPos];

  }

  }

}