/** * Source Code first verified at https://etherscan.io on Friday, April 26, 2019 (UTC) */ pragma solidity ^0.5.3; contract Operator { uint256 public ONE_DAY = 86400; uint256 public MIN_DEP = 1 ether; uint256 public MAX_DEP = 100 ether; address public admin; address public admin2; address public querierAddress; uint256 public depositedAmountGross = 0; uint256 public paySystemCommissionTimes = 1; uint256 public payDailyIncomeTimes = 1; uint256 public lastPaySystemCommission = now; uint256 public lastPayDailyIncome = now; uint256 public contractStartAt = now; uint256 public lastReset = now; address payable public operationFund = 0xa4048772583220896ec93316616778B4EbC70F9d; address[] public investorAddresses; bytes32[] public investmentIds; bytes32[] public withdrawalIds; bytes32[] public maxOutIds; mapping (address => Investor) investors; mapping (bytes32 => Investment) public investments; mapping (bytes32 => Withdrawal) public withdrawals; mapping (bytes32 => MaxOut) public maxOuts; mapping (address => WithdrawAccount) public withdrawAccounts; uint256 additionNow = 0; uint256 public maxLevelsAddSale = 200; uint256 public maximumMaxOutInWeek = 2; bool public importing = true; Vote public currentVote; struct WithdrawAccount { address initialAddress; address currentWithdrawalAddress; address requestingWithdrawalAddress; } struct Vote { uint256 startTime; string reason; mapping (address => uint8) votes; address payable emergencyAddress; uint256 yesPoint; uint256 noPoint; uint256 totalPoint; } struct Investment { bytes32 id; uint256 at; uint256 amount; address investor; address nextInvestor; bool nextBranch; } struct Withdrawal { bytes32 id; uint256 at; uint256 amount; address investor; address presentee; uint256 reason; uint256 times; } struct Investor { address parent; address leftChild; address rightChild; address presenter; uint256 generation; uint256 depositedAmount; uint256 withdrewAmount; bool isDisabled; uint256 lastMaxOut; uint256 maxOutTimes; uint256 maxOutTimesInWeek; uint256 totalSell; uint256 sellThisMonth; uint256 rightSell; uint256 leftSell; uint256 reserveCommission; uint256 dailyIncomeWithrewAmount; uint256 registerTime; uint256 minDeposit; bytes32[] investments; bytes32[] withdrawals; } struct MaxOut { bytes32 id; address investor; uint256 times; uint256 at; } constructor () public { admin = msg.sender; } modifier mustBeAdmin() { require(msg.sender == admin || msg.sender == querierAddress || msg.sender == admin2); _; } modifier mustBeImporting() { require(importing); require(msg.sender == querierAddress || msg.sender == admin); _; } function () payable external { deposit(); } function getNow() internal view returns(uint256) { return additionNow + now; } function depositProcess(address sender) internal { Investor storage investor = investors[sender]; require(investor.generation != 0); if (investor.depositedAmount == 0) require(msg.value >= investor.minDeposit); require(investor.maxOutTimesInWeek < maximumMaxOutInWeek); require(investor.maxOutTimes < 50); require(investor.maxOutTimes == 0 || getNow() - investor.lastMaxOut < ONE_DAY * 7 || investor.depositedAmount != 0); depositedAmountGross += msg.value; bytes32 id = keccak256(abi.encodePacked(block.number, getNow(), sender, msg.value)); uint256 investmentValue = investor.depositedAmount + msg.value <= MAX_DEP ? msg.value : MAX_DEP - investor.depositedAmount; if (investmentValue == 0) return; bool nextBranch = investors[investor.parent].leftChild == sender; Investment memory investment = Investment({ id: id, at: getNow(), amount: investmentValue, investor: sender, nextInvestor: investor.parent, nextBranch: nextBranch }); investments[id] = investment; processInvestments(id); investmentIds.push(id); } function pushNewMaxOut(address investorAddress, uint256 times, uint256 depositedAmount) internal { bytes32 id = keccak256(abi.encodePacked(block.number, getNow(), investorAddress, times)); MaxOut memory maxOut = MaxOut({ id: id, at: getNow(), investor: investorAddress, times: times }); maxOutIds.push(id); maxOuts[id] = maxOut; investors[investorAddress].minDeposit = depositedAmount; } function deposit() payable public { depositProcess(msg.sender); } function processInvestments(bytes32 investmentId) internal { Investment storage investment = investments[investmentId]; uint256 amount = investment.amount; Investor storage investor = investors[investment.investor]; investor.investments.push(investmentId); investor.depositedAmount += amount; address payable presenterAddress = address(uint160(investor.presenter)); Investor storage presenter = investors[presenterAddress]; if (presenterAddress != address(0)) { presenter.totalSell += amount; presenter.sellThisMonth += amount; } if (presenter.depositedAmount >= MIN_DEP && !presenter.isDisabled) { sendEtherForInvestor(presenterAddress, amount / 10, 1, investment.investor, 0); } } function getWithdrawAddress(address payable initialAddress) public view returns (address payable) { WithdrawAccount memory withdrawAccount = withdrawAccounts[initialAddress]; address withdrawAddress = withdrawAccount.currentWithdrawalAddress; if (withdrawAddress != address(0)) return address(uint160(withdrawAddress)); return initialAddress; } function requestChangeWithdrawAddress(address newAddress) public { require(investors[msg.sender].depositedAmount > 0); WithdrawAccount storage currentWithdrawAccount = withdrawAccounts[msg.sender]; if (currentWithdrawAccount.initialAddress != address(0)) { currentWithdrawAccount.requestingWithdrawalAddress = newAddress; return; } WithdrawAccount memory withdrawAccount = WithdrawAccount({ initialAddress: msg.sender, currentWithdrawalAddress: msg.sender, requestingWithdrawalAddress: newAddress }); withdrawAccounts[msg.sender] = withdrawAccount; } function acceptChangeWithdrawAddress(address initialAddress, address requestingWithdrawalAddress) public mustBeAdmin { WithdrawAccount storage withdrawAccount = withdrawAccounts[initialAddress]; require(withdrawAccount.requestingWithdrawalAddress == requestingWithdrawalAddress); withdrawAccount.requestingWithdrawalAddress = address(0); withdrawAccount.currentWithdrawalAddress = requestingWithdrawalAddress; } function addSellForParents(bytes32 investmentId) public mustBeAdmin { Investment storage investment = investments[investmentId]; require(investment.nextInvestor != address(0)); uint256 amount = investment.amount; uint256 loopCount = 0; while (investment.nextInvestor != address(0) && loopCount < maxLevelsAddSale) { Investor storage investor = investors[investment.nextInvestor]; if (investment.nextBranch) investor.leftSell += amount; else investor.rightSell += amount; investment.nextBranch = investors[investor.parent].leftChild == investment.nextInvestor; investment.nextInvestor = investor.parent; loopCount++; } } function sendEtherForInvestor(address payable investorAddress, uint256 value, uint256 reason, address presentee, uint256 times) internal { if (value == 0 && reason != 100) return; if (investorAddress == address(0)) return; Investor storage investor = investors[investorAddress]; uint256 unpaidSystemCommission = getUnpaidSystemCommission(investorAddress); uint256 totalPaidAfterThisTime = investor.reserveCommission + getDailyIncomeForUser(investorAddress) + unpaidSystemCommission; if (reason == 1) totalPaidAfterThisTime += value; if (totalPaidAfterThisTime + investor.withdrewAmount >= 3 * investor.depositedAmount) { payWithMaxOut(totalPaidAfterThisTime, investorAddress, unpaidSystemCommission); return; } if (investor.reserveCommission > 0) payWithNoMaxOut(investor.reserveCommission, investorAddress, 4, address(0), 0); payWithNoMaxOut(value, investorAddress, reason, presentee, times); } function payWithNoMaxOut(uint256 amountToPay, address payable investorAddress, uint256 reason, address presentee, uint256 times) internal { investors[investorAddress].withdrewAmount += amountToPay; if (reason == 4) investors[investorAddress].reserveCommission = 0; if (reason == 3) resetSystemCommision(investorAddress, times); if (reason == 2) investors[investorAddress].dailyIncomeWithrewAmount += amountToPay; pay(amountToPay, investorAddress, reason, presentee, times); } function payWithMaxOut(uint256 totalPaidAfterThisTime, address payable investorAddress, uint256 unpaidSystemCommission) internal { Investor storage investor = investors[investorAddress]; uint256 amountToPay = investor.depositedAmount * 3 - investor.withdrewAmount; uint256 amountToReserve = totalPaidAfterThisTime - amountToPay; if (unpaidSystemCommission > 0) resetSystemCommision(investorAddress, 0); investor.maxOutTimes++; investor.maxOutTimesInWeek++; uint256 oldDepositedAmount = investor.depositedAmount; investor.depositedAmount = 0; investor.withdrewAmount = 0; investor.lastMaxOut = getNow(); investor.dailyIncomeWithrewAmount = 0; investor.reserveCommission = amountToReserve; pushNewMaxOut(investorAddress, investor.maxOutTimes, oldDepositedAmount); pay(amountToPay, investorAddress, 0, address(0), 0); } function pay(uint256 amountToPay, address payable investorAddress, uint256 reason, address presentee, uint256 times) internal { if (amountToPay == 0) return; // TODO REPLACE address(uint160(admin)).transfer(amountToPay); // address payable withdrawAddress = getWithdrawAddress(investorAddress); // withdrawAddress.transfer(amountToPay / 100 * 90); // operationFund.transfer(amountToPay / 100 * 10); bytes32 id = keccak256(abi.encodePacked(block.difficulty, getNow(), investorAddress, amountToPay, reason)); Withdrawal memory withdrawal = Withdrawal({ id: id, at: getNow(), amount: amountToPay, investor: investorAddress, presentee: presentee, times: times, reason: reason }); withdrawals[id] = withdrawal; investors[investorAddress].withdrawals.push(id); withdrawalIds.push(id); } function getAllIncomeTilNow(address investorAddress) internal view returns(uint256 allIncome) { Investor memory investor = investors[investorAddress]; uint256 unpaidDailyIncome = getDailyIncomeForUser(investorAddress); uint256 withdrewAmount = investor.withdrewAmount; uint256 unpaidSystemCommission = getUnpaidSystemCommission(investorAddress); uint256 allIncomeNow = unpaidDailyIncome + withdrewAmount + unpaidSystemCommission; return allIncomeNow; } function putPresentee(address presenterAddress, address presenteeAddress, address parentAddress, bool isLeft) public mustBeAdmin { Investor storage presenter = investors[presenterAddress]; Investor storage parent = investors[parentAddress]; if (investorAddresses.length != 0) { require(presenter.generation != 0); require(parent.generation != 0); if (isLeft) { require(parent.leftChild == address(0)); } else { require(parent.rightChild == address(0)); } } Investor memory investor = Investor({ parent: parentAddress, leftChild: address(0), rightChild: address(0), presenter: presenterAddress, generation: parent.generation + 1, depositedAmount: 0, withdrewAmount: 0, isDisabled: false, lastMaxOut: getNow(), maxOutTimes: 0, maxOutTimesInWeek: 0, totalSell: 0, sellThisMonth: 0, registerTime: getNow(), investments: new bytes32[](0), withdrawals: new bytes32[](0), minDeposit: MIN_DEP, rightSell: 0, leftSell: 0, reserveCommission: 0, dailyIncomeWithrewAmount: 0 }); investors[presenteeAddress] = investor; investorAddresses.push(presenteeAddress); if (parent.generation == 0) return; if (isLeft) { parent.leftChild = presenteeAddress; } else { parent.rightChild = presenteeAddress; } } function getDailyIncomeForUser(address investorAddress) internal view returns(uint256 amount) { Investor memory investor = investors[investorAddress]; uint256 investmentLength = investor.investments.length; uint256 dailyIncome = 0; for (uint256 i = 0; i < investmentLength; i++) { Investment memory investment = investments[investor.investments[i]]; if (investment.at < investor.lastMaxOut) continue; if (getNow() - investment.at >= ONE_DAY) { uint256 numberOfDay = (getNow() - investment.at) / ONE_DAY; uint256 totalDailyIncome = numberOfDay * investment.amount / 100; dailyIncome = totalDailyIncome + dailyIncome; } } return dailyIncome - investor.dailyIncomeWithrewAmount; } function payDailyIncomeForInvestor(address payable investorAddress, uint256 times) public mustBeAdmin { uint256 dailyIncome = getDailyIncomeForUser(investorAddress); Investor storage investor = investors[investorAddress]; if (times > ONE_DAY) { uint256 investmentLength = investor.investments.length; bytes32 lastInvestmentId = investor.investments[investmentLength - 1]; investments[lastInvestmentId].at -= times; investors[investorAddress].lastMaxOut = investments[lastInvestmentId].at; return; } if (investor.isDisabled) return; sendEtherForInvestor(investorAddress, dailyIncome, 2, address(0), times); } function payDailyIncomeByIndex(uint256 from, uint256 to) public mustBeAdmin{ require(from >= 0 && to < investorAddresses.length); for(uint256 i = from; i <= to; i++) { payDailyIncomeForInvestor(address(uint160(investorAddresses[i])), payDailyIncomeTimes); } } function getUnpaidSystemCommission(address investorAddress) public view returns(uint256 unpaid) { Investor memory investor = investors[investorAddress]; uint256 depositedAmount = investor.depositedAmount; uint256 totalSell = investor.totalSell; uint256 leftSell = investor.leftSell; uint256 rightSell = investor.rightSell; uint256 sellThisMonth = investor.sellThisMonth; uint256 sellToPaySystemCommission = rightSell < leftSell ? rightSell : leftSell; uint256 commission = sellToPaySystemCommission * getPercentage(depositedAmount, totalSell, sellThisMonth) / 100; return commission; } function paySystemCommissionInvestor(address payable investorAddress, uint256 times) public mustBeAdmin { Investor storage investor = investors[investorAddress]; if (investor.isDisabled) return; uint256 systemCommission = getUnpaidSystemCommission(investorAddress); sendEtherForInvestor(investorAddress, systemCommission, 3, address(0), times); } function resetSystemCommision(address investorAddress, uint256 times) internal { Investor storage investor = investors[investorAddress]; if (paySystemCommissionTimes > 3 && times != 0) { investor.rightSell = 0; investor.leftSell = 0; } else if (investor.rightSell >= investor.leftSell) { investor.rightSell = investor.rightSell - investor.leftSell; investor.leftSell = 0; } else { investor.leftSell = investor.leftSell - investor.rightSell; investor.rightSell = 0; } if (times != 0) investor.sellThisMonth = 0; } function paySystemCommissionByIndex(uint256 from, uint256 to) public mustBeAdmin { require(from >= 0 && to < investorAddresses.length); if (getNow() <= 30 * ONE_DAY + contractStartAt) return; for(uint256 i = from; i <= to; i++) { paySystemCommissionInvestor(address(uint160(investorAddresses[i])), paySystemCommissionTimes); } } function finishPayDailyIncome() public mustBeAdmin { lastPayDailyIncome = getNow(); payDailyIncomeTimes++; } function finishPaySystemCommission() public mustBeAdmin { lastPaySystemCommission = getNow(); paySystemCommissionTimes++; } function resetGame(uint256 from, uint256 to) public mustBeAdmin { require(from >= 0 && to < investorAddresses.length); require(currentVote.startTime != 0); require(getNow() - currentVote.startTime > 3 * ONE_DAY); require(currentVote.yesPoint > currentVote.totalPoint / 2); require(currentVote.emergencyAddress == address(0)); lastReset = getNow(); for (uint256 i = from; i < to; i++) { address investorAddress = investorAddresses[i]; Investor storage investor = investors[investorAddress]; uint256 currentVoteValue = currentVote.votes[investorAddress] != 0 ? currentVote.votes[investorAddress] : 2; if (currentVoteValue == 2) { if (investor.maxOutTimes > 0 || (investor.withdrewAmount >= investor.depositedAmount && investor.withdrewAmount != 0)) { investor.lastMaxOut = getNow(); investor.depositedAmount = 0; investor.withdrewAmount = 0; investor.dailyIncomeWithrewAmount = 0; } investor.reserveCommission = 0; investor.rightSell = 0; investor.leftSell = 0; investor.totalSell = 0; investor.sellThisMonth = 0; } else { if (investor.maxOutTimes > 0 || (investor.withdrewAmount >= investor.depositedAmount && investor.withdrewAmount != 0)) { investor.isDisabled = true; investor.reserveCommission = 0; investor.lastMaxOut = getNow(); investor.depositedAmount = 0; investor.withdrewAmount = 0; investor.dailyIncomeWithrewAmount = 0; } investor.reserveCommission = 0; investor.rightSell = 0; investor.leftSell = 0; investor.totalSell = 0; investor.sellThisMonth = 0; } } } function stopGame(uint256 percent, uint256 from, uint256 to) mustBeAdmin public { require(currentVote.startTime != 0); require(getNow() - currentVote.startTime > 3 * ONE_DAY); require(currentVote.noPoint > currentVote.totalPoint / 2); require(currentVote.emergencyAddress == address(0)); require(percent <= 50); require(from >= 0 && to < investorAddresses.length); for (uint256 i = from; i <= to; i++) { address payable investorAddress = address(uint160(investorAddresses[i])); Investor storage investor = investors[investorAddress]; if (investor.maxOutTimes > 0) continue; if (investor.isDisabled) continue; uint256 depositedAmount = investor.depositedAmount; uint256 withdrewAmount = investor.withdrewAmount; if (withdrewAmount >= depositedAmount / 2) continue; sendEtherForInvestor(investorAddress, depositedAmount * percent / 100 - withdrewAmount, 6, address(0), 0); } } function revivalInvestor(address investor) public mustBeAdmin { investors[investor].lastMaxOut = getNow(); } function payToReachMaxOut(address payable investorAddress) public mustBeAdmin { uint256 unpaidSystemCommissions = getUnpaidSystemCommission(investorAddress); uint256 unpaidDailyIncomes = getDailyIncomeForUser(investorAddress); uint256 withdrewAmount = investors[investorAddress].withdrewAmount; uint256 depositedAmount = investors[investorAddress].depositedAmount; uint256 reserveCommission = investors[investorAddress].reserveCommission; require(depositedAmount > 0 && withdrewAmount + unpaidSystemCommissions + unpaidDailyIncomes + reserveCommission >= 3 * depositedAmount); sendEtherForInvestor(investorAddress, 0, 100, address(0), 0); } function resetMaxOutInWeek(uint256 from, uint256 to) public mustBeAdmin { require(from >= 0 && to < investorAddresses.length); for (uint256 i = from; i < to; i++) { address investorAddress = investorAddresses[i]; if (investors[investorAddress].maxOutTimesInWeek == 0) continue; investors[investorAddress].maxOutTimesInWeek = 0; } } function setMaximumMaxOutTimes(address investorAddress, uint256 times) public mustBeAdmin{ investors[investorAddress].maxOutTimes = times; } function disableInvestor(address investorAddress) public mustBeAdmin { Investor storage investor = investors[investorAddress]; investor.isDisabled = true; } function enableInvestor(address investorAddress) public mustBeAdmin { Investor storage investor = investors[investorAddress]; investor.isDisabled = false; } function donate() payable public { depositedAmountGross += msg.value; } function getTotalSellLevel(uint256 totalSell) internal pure returns (uint256 level){ if (totalSell < 30 ether) return 0; if (totalSell < 60 ether) return 1; if (totalSell < 90 ether) return 2; if (totalSell < 120 ether) return 3; if (totalSell < 150 ether) return 4; return 5; } function getSellThisMonthLevel(uint256 sellThisMonth) internal pure returns (uint256 level){ if (sellThisMonth < 2 ether) return 0; if (sellThisMonth < 4 ether) return 1; if (sellThisMonth < 6 ether) return 2; if (sellThisMonth < 8 ether) return 3; if (sellThisMonth < 10 ether) return 4; return 5; } function getDepositLevel(uint256 depositedAmount) internal pure returns (uint256 level){ if (depositedAmount < 2 ether) return 0; if (depositedAmount < 4 ether) return 1; if (depositedAmount < 6 ether) return 2; if (depositedAmount < 8 ether) return 3; if (depositedAmount < 10 ether) return 4; return 5; } function getPercentage(uint256 depositedAmount, uint256 totalSell, uint256 sellThisMonth) internal pure returns(uint256 level) { uint256 totalSellLevel = getTotalSellLevel(totalSell); uint256 depLevel = getDepositLevel(depositedAmount); uint256 sellThisMonthLevel = getSellThisMonthLevel(sellThisMonth); uint256 min12 = totalSellLevel < depLevel ? totalSellLevel : depLevel; uint256 minLevel = sellThisMonthLevel < min12 ? sellThisMonthLevel : min12; return minLevel * 2; } function stringToBytes32(string memory source) internal pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) return 0x0; assembly { result := mload(add(source, 32)) } } function getInvestor(address investorAddress) view public returns (address[] memory addresses, bool isDisabled, uint256[] memory numbers) { addresses = new address[](4); numbers = new uint256[](16); Investor memory investor = investors[investorAddress]; addresses[0] = investor.parent; addresses[1] = investor.leftChild; addresses[2] = investor.rightChild; addresses[3] = investor.presenter; numbers[0] = investor.generation; numbers[1] = investor.depositedAmount; numbers[2] = investor.withdrewAmount; numbers[3] = investor.lastMaxOut; numbers[4] = investor.maxOutTimes; numbers[5] = investor.maxOutTimesInWeek; numbers[6] = investor.totalSell; numbers[7] = investor.sellThisMonth; numbers[8] = investor.rightSell; numbers[9] = investor.leftSell; numbers[10] = investor.reserveCommission; numbers[11] = investor.dailyIncomeWithrewAmount; numbers[12] = investor.registerTime; numbers[13] = getUnpaidSystemCommission(investorAddress); numbers[14] = getDailyIncomeForUser(investorAddress); numbers[15] = investor.minDeposit; return (addresses, investor.isDisabled, numbers); } function getInvestorLength() view public returns(uint256) { return investorAddresses.length; } function getMaxOutsLength() view public returns(uint256) { return maxOutIds.length; } function getNodesAddresses(address rootNodeAddress) public view returns(address[] memory){ uint256 maxLength = investorAddresses.length; address[] memory nodes = new address[](maxLength); nodes[0] = rootNodeAddress; uint256 processIndex = 0; uint256 nextIndex = 1; while (processIndex != nextIndex) { Investor memory currentInvestor = investors[nodes[processIndex++]]; if (currentInvestor.leftChild != address(0)) nodes[nextIndex++] = currentInvestor.leftChild; if (currentInvestor.rightChild != address(0)) nodes[nextIndex++] = currentInvestor.rightChild; } return nodes; } function getInvestmentsLength () public view returns(uint256 length) { return investmentIds.length; } function getWithdrawalsLength() public view returns(uint256 length) { return withdrawalIds.length; } function importInvestor(address[] memory addresses, bool isDisabled, uint256[] memory numbers) public mustBeImporting { if (investors[addresses[4]].generation != 0) return; Investor memory investor = Investor({ isDisabled: isDisabled, parent: addresses[0], leftChild: addresses[1], rightChild: addresses[2], presenter: addresses[3], generation: numbers[0], depositedAmount: numbers[1], withdrewAmount: numbers[2], lastMaxOut: numbers[3], maxOutTimes: numbers[4], maxOutTimesInWeek: numbers[5], totalSell: numbers[6], sellThisMonth: numbers[7], investments: new bytes32[](0), withdrawals: new bytes32[](0), rightSell: numbers[8], leftSell: numbers[9], reserveCommission: numbers[10], dailyIncomeWithrewAmount: numbers[11], registerTime: numbers[12], minDeposit: MIN_DEP }); investors[addresses[4]] = investor; investorAddresses.push(addresses[4]); } function importInvestments(bytes32 id, uint256 at, uint256 amount, address investorAddress) public mustBeImporting { if (investments[id].at != 0) return; Investment memory investment = Investment({ id: id, at: at, amount: amount, investor: investorAddress, nextInvestor: address(0), nextBranch: false }); investments[id] = investment; investmentIds.push(id); Investor storage investor = investors[investorAddress]; investor.investments.push(id); depositedAmountGross += amount; } function importWithdrawals(bytes32 id, uint256 at, uint256 amount, address investorAddress, address presentee, uint256 reason, uint256 times) public mustBeImporting { if (withdrawals[id].at != 0) return; Withdrawal memory withdrawal = Withdrawal({ id: id, at: at, amount: amount, investor: investorAddress, presentee: presentee, times: times, reason: reason }); withdrawals[id] = withdrawal; Investor storage investor = investors[investorAddress]; investor.withdrawals.push(id); withdrawalIds.push(id); } function finishImporting() public mustBeAdmin { importing = false; } function finalizeVotes(uint256 from, uint256 to, bool isRemoving) public mustBeAdmin { require(getNow() - currentVote.startTime > 3 * ONE_DAY); for (uint256 index = from; index < to; index++) { address investorAddress = investorAddresses[index]; if (isRemoving && currentVote.votes[investorAddress] == 3) { currentVote.votes[investorAddress] = 0; continue; } if (currentVote.votes[investorAddress] == 0) { currentVote.yesPoint += 1; } currentVote.votes[investorAddress] = 3; } } function createVote(string memory reason, address payable emergencyAddress) public mustBeAdmin { require(currentVote.startTime == 0); currentVote = Vote({ startTime: getNow(), reason: reason, emergencyAddress: emergencyAddress, yesPoint: 0, noPoint: 0, totalPoint: investorAddresses.length }); } function removeVote() public mustBeAdmin { currentVote = Vote({ startTime: 0, reason: '', emergencyAddress: address(0), yesPoint: 0, noPoint: 0, totalPoint: 0 }); } function sendEtherToNewContract() public mustBeAdmin { require(currentVote.startTime != 0); require(getNow() - currentVote.startTime > 3 * ONE_DAY); require(currentVote.yesPoint > currentVote.totalPoint / 2); require(currentVote.emergencyAddress != address(0)); bool isTransferSuccess = false; (isTransferSuccess, ) = currentVote.emergencyAddress.call.value(address(this).balance)(""); if (!isTransferSuccess) revert(); } function voteProcess(address investor, bool isYes) internal { require(investors[investor].depositedAmount > 0); require(!investors[investor].isDisabled); require(getNow() - currentVote.startTime < 3 * ONE_DAY); uint8 newVoteValue = isYes ? 2 : 1; uint8 currentVoteValue = currentVote.votes[investor]; require(newVoteValue != currentVoteValue); updateVote(isYes); if (currentVoteValue == 0) return; if (isYes) { currentVote.noPoint -= getVoteShare(); } else { currentVote.yesPoint -= getVoteShare(); } } function vote(bool isYes) public { voteProcess(msg.sender, isYes); } function updateVote(bool isYes) internal { currentVote.votes[msg.sender] = isYes ? 2 : 1; if (isYes) { currentVote.yesPoint += getVoteShare(); } else { currentVote.noPoint += getVoteShare(); } } function getVoteShare() public view returns(uint256) { if (investors[msg.sender].generation >= 3) return 1; if (currentVote.totalPoint > 40) return currentVote.totalPoint / 20; return 2; } function setQuerier(address _querierAddress) public mustBeAdmin { querierAddress = _querierAddress; } function setAdmin2(address _admin2) public mustBeAdmin { admin2 = _admin2; } function setInitialValue(uint256 _paySystemCommissionTimes, uint256 _payDailyIncomeTimes, uint256 _lastPaySystemCommission, uint256 _lastPayDailyIncome, uint256 _contractStartAt, uint256 _lastReset) public mustBeImporting { paySystemCommissionTimes = _paySystemCommissionTimes; payDailyIncomeTimes = _payDailyIncomeTimes; lastPaySystemCommission = _lastPaySystemCommission; lastPayDailyIncome = _lastPayDailyIncome; contractStartAt = _contractStartAt; lastReset = _lastReset; } function depositFor(address investor) public payable mustBeAdmin { depositProcess(investor); } function setInvestorTestInfo(address investorAddress, uint256 totalSell, uint256 sellThisMonth, uint256 rightSell, uint256 leftSell) public mustBeAdmin { Investor storage investor = investors[investorAddress]; require(investor.generation > 0); investor.totalSell = totalSell; investor.sellThisMonth = sellThisMonth; investor.rightSell = rightSell; investor.leftSell = leftSell; } }