文件 1 的 4:Dequest.sol
pragma solidity ^0.6.0;
import "https://github.com/uniswap/uniswap-v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "https://github.com/uniswap/uniswap-v2-core/contracts/interfaces/IUniswapV2Factory.sol";
contract DequestBase {
address public owner;
address public uniswapRouter;
address public tokenAddr;
uint8 public constant LAST_LEVEL = 8;
mapping(address => User) public users;
mapping(uint256 => address) public idToAddress;
uint256 public lastUserId = 100101;
mapping(uint8 => uint256) public levelPrice;
uint8 public state;
mapping(uint8 => uint256) public stats;
address investor;
address public signer;
struct User {
uint256 id;
address referrer;
uint256 partnersCount;
mapping(uint8 => bool) activeX3Levels;
mapping(uint8 => bool) activeX6Levels;
mapping(uint8 => X3) x3Matrix;
mapping(uint8 => X6) x6Matrix;
}
struct X3 {
address currentReferrer;
address[] referrals;
bool blocked;
uint256 reinvestCount;
uint256 estEarn;
}
struct X6 {
address currentReferrer;
address[] firstLevelReferrals;
address[] secondLevelReferrals;
bool blocked;
uint256 reinvestCount;
uint256 estEarn;
address closedPart;
}
event Registration(address indexed user, address indexed referrer, uint256 indexed userId, uint256 referrerId);
event Reinvest(address indexed user, address indexed currentReferrer, address indexed caller, uint8 matrix, uint8 level);
event Upgrade(address indexed user, address indexed referrer, uint8 matrix, uint8 level);
event NewUserPlace(address indexed user, address indexed referrer, uint8 matrix, uint8 level, uint8 place);
event MissedERC20Receive(address indexed receiver, address indexed from, uint8 matrix, uint8 level);
event SentExtraERC20Dividends(address indexed from, address indexed receiver, uint8 matrix, uint8 level);
event ERC20Dividens(address indexed receiver, uint8 indexed matrix, uint8 indexed level, uint256 fromAmount, uint256 toAmount);
event InvestorDividens(address indexed receiver, uint8 indexed matrix, uint8 indexed level, uint256 amount);
modifier isNotInit() {
require(state == 0, "Dequest: already initialized.");
_;
}
modifier isOwner() {
require(msg.sender == owner || address(0) == owner, "Dequest: Not owner");
_;
}
}
contract DequestSwapable {
function swap(address _uniswapRouter, address _tokenAddr, uint256 _value, address _receiver, uint256 _deadline) internal returns (uint256 minAmount) {
IUniswapV2Router02 router = IUniswapV2Router02(_uniswapRouter);
address[] memory path = new address[](2);
path[0] = router.WETH();
path[1] = _tokenAddr;
minAmount = router.getAmountsOut(_value, path)[1] * 95 / 100;
router.swapExactETHForTokensSupportingFeeOnTransferTokens{ value : _value }(minAmount, path, _receiver, _deadline);
}
}
contract Dequest is DequestBase, DequestSwapable {
constructor() public {
owner = msg.sender;
}
function init(uint256 _startPrice, address _uniswapRouter, address _tokenAddr) external isNotInit isOwner returns(bool) {
owner = msg.sender;
investor = msg.sender;
state = 1;
lastUserId = 100101;
uniswapRouter = _uniswapRouter;
tokenAddr = _tokenAddr;
levelPrice[1] = _startPrice;
for (uint8 i = 2; i <= LAST_LEVEL; i++) {
levelPrice[i] = levelPrice[i-1] * 2;
}
User memory user = User({
id: lastUserId,
referrer: address(0),
partnersCount: uint256(0)
});
users[owner] = user;
idToAddress[lastUserId] = owner;
for (uint8 i = 1; i <= LAST_LEVEL; i++) {
users[owner].activeX3Levels[i] = true;
users[owner].activeX6Levels[i] = true;
}
lastUserId++;
}
function changeOwner(address _owner) external isOwner returns (bool) {
owner = _owner;
return true;
}
function changeInvestor(address _investor) external isOwner returns (bool) {
investor = _investor;
return true;
}
function changeSigner(address _signer) external isOwner returns (bool) {
signer = _signer;
return true;
}
function changeState(uint8 _state) external isOwner returns (bool) {
state = _state;
return true;
}
function updateSwapInfo(address _uniswapRouter, address _tokenAddr) external isOwner returns (bool) {
uniswapRouter = _uniswapRouter;
tokenAddr = _tokenAddr;
return true;
}
function registrationExt(address referrerAddress, uint256 _deadline) external payable {
registration(msg.sender, referrerAddress, _deadline, true);
}
function registrationExtAdmin(address userAddr, address referrerAddress, uint256 _deadline, uint8 v, bytes32 r, bytes32 s) external payable {
require(signer != address(0x0), "Dequest: Invalid signer [1]");
bytes32 message = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encode(userAddr, referrerAddress, _deadline, msg.sender))));
require(ecrecover(message, v, r, s) == signer, "Dequest: Invalid signer [2]");
require(now <= _deadline, "Dequest: Request expired");
registration(userAddr, referrerAddress, _deadline, false);
for (uint8 i = 2; i <= LAST_LEVEL; i++) {
newLevel(1, i, _deadline, userAddr, false);
newLevel(2, i, _deadline, userAddr, false);
}
}
function buyNewLevel(uint8 matrix, uint8 level, uint256 _deadline) external payable {
newLevel(matrix, level, _deadline, msg.sender, true);
}
function newLevel(uint8 matrix, uint8 level, uint256 _deadline, address userAddr, bool withPayment) internal {
require(isUserExists(userAddr), "Dequest: user is not exists. Register first.");
require(matrix == 1 || matrix == 2, "Dequest: invalid matrix");
if (withPayment) {
require(msg.value == levelPrice[level], "Dequest: invalid price");
}
require(level > 1 && level <= LAST_LEVEL, "Dequest: invalid level");
if (matrix == 1) {
require(!users[userAddr].activeX3Levels[level], "Dequest: level already activated");
if (users[userAddr].x3Matrix[level-1].blocked) {
users[userAddr].x3Matrix[level-1].blocked = false;
}
address freeX3Referrer = findFreeX3Referrer(userAddr, level);
users[userAddr].x3Matrix[level].currentReferrer = freeX3Referrer;
users[userAddr].activeX3Levels[level] = true;
updateX3Referrer(userAddr, freeX3Referrer, level, _deadline, withPayment);
emit Upgrade(userAddr, freeX3Referrer, 1, level);
} else {
require(!users[userAddr].activeX6Levels[level], "Dequest: level already activated");
if (users[userAddr].x6Matrix[level-1].blocked) {
users[userAddr].x6Matrix[level-1].blocked = false;
}
address freeX6Referrer = findFreeX6Referrer(userAddr, level);
users[userAddr].activeX6Levels[level] = true;
updateX6Referrer(userAddr, freeX6Referrer, level, _deadline, withPayment);
emit Upgrade(userAddr, freeX6Referrer, 2, level);
}
}
function registration(address userAddress, address referrerAddress, uint256 _deadline, bool withPayment) internal {
uint256 price = levelPrice[1] * 2;
if (withPayment) {
require(msg.value == price, "Dequest: invalid registration cost");
}
require(!isUserExists(userAddress), "Dequest: user exists");
require(isUserExists(referrerAddress), "Dequest: referrer not exists");
uint32 size;
assembly {
size := extcodesize(userAddress)
}
require(size == 0, "Dequest: cannot be a contract");
User memory user = User({
id: lastUserId,
referrer: referrerAddress,
partnersCount: 0
});
users[userAddress] = user;
idToAddress[lastUserId] = userAddress;
users[userAddress].referrer = referrerAddress;
users[userAddress].activeX3Levels[1] = true;
users[userAddress].activeX6Levels[1] = true;
lastUserId++;
users[referrerAddress].partnersCount++;
address freeX3Referrer = findFreeX3Referrer(userAddress, 1);
users[userAddress].x3Matrix[1].currentReferrer = freeX3Referrer;
updateX3Referrer(userAddress, freeX3Referrer, 1, _deadline, withPayment);
updateX6Referrer(userAddress, findFreeX6Referrer(userAddress, 1), 1, _deadline, withPayment);
emit Registration(userAddress, referrerAddress, users[userAddress].id, users[referrerAddress].id);
stats[0]++;
}
function updateX3Referrer(address userAddress, address referrerAddress, uint8 level, uint256 _deadline, bool withPayment) internal {
users[referrerAddress].x3Matrix[level].referrals.push(userAddress);
if (users[referrerAddress].x3Matrix[level].referrals.length < 3) {
emit NewUserPlace(userAddress, referrerAddress, 1, level, uint8(users[referrerAddress].x3Matrix[level].referrals.length));
sendERC20Dividends(referrerAddress, userAddress, 1, level, _deadline, withPayment);
return ;
}
emit NewUserPlace(userAddress, referrerAddress, 1, level, 3);
users[referrerAddress].x3Matrix[level].referrals = new address[](0);
if (!users[referrerAddress].activeX3Levels[level+1] && level != LAST_LEVEL) {
users[referrerAddress].x3Matrix[level].blocked = true;
}
if (referrerAddress != owner) {
address freeReferrerAddress = findFreeX3Referrer(referrerAddress, level);
if (users[referrerAddress].x3Matrix[level].currentReferrer != freeReferrerAddress) {
users[referrerAddress].x3Matrix[level].currentReferrer = freeReferrerAddress;
}
users[referrerAddress].x3Matrix[level].reinvestCount++;
emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 1, level);
updateX3Referrer(referrerAddress, freeReferrerAddress, level, _deadline, withPayment);
} else {
sendERC20Dividends(owner, userAddress, 1, level, _deadline, withPayment);
users[owner].x3Matrix[level].reinvestCount++;
emit Reinvest(owner, address(0), userAddress, 1, level);
}
}
function updateX6Referrer(address userAddress, address referrerAddress, uint8 level, uint256 _deadline, bool withPayment) internal {
require(users[referrerAddress].activeX6Levels[level], "Dequest: 500. Referrer level is inactive");
if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length < 2) {
users[referrerAddress].x6Matrix[level].firstLevelReferrals.push(userAddress);
emit NewUserPlace(userAddress, referrerAddress, 2, level, uint8(users[referrerAddress].x6Matrix[level].firstLevelReferrals.length));
users[userAddress].x6Matrix[level].currentReferrer = referrerAddress;
if (referrerAddress == owner) {
sendERC20Dividends(referrerAddress, userAddress, 2, level, _deadline, withPayment);
return ;
}
address ref = users[referrerAddress].x6Matrix[level].currentReferrer;
users[ref].x6Matrix[level].secondLevelReferrals.push(userAddress);
uint256 len = users[ref].x6Matrix[level].firstLevelReferrals.length;
if ((len == 2) &&
(users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) &&
(users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress)) {
if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
emit NewUserPlace(userAddress, ref, 2, level, 5);
} else {
emit NewUserPlace(userAddress, ref, 2, level, 6);
}
} else if ((len == 1 || len == 2) &&
users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) {
if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
emit NewUserPlace(userAddress, ref, 2, level, 3);
} else {
emit NewUserPlace(userAddress, ref, 2, level, 4);
}
} else if (len == 2 && users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress) {
if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
emit NewUserPlace(userAddress, ref, 2, level, 5);
} else {
emit NewUserPlace(userAddress, ref, 2, level, 6);
}
}
return updateX6ReferrerSecondLevel(userAddress, ref, level, _deadline, withPayment);
}
users[referrerAddress].x6Matrix[level].secondLevelReferrals.push(userAddress);
if (users[referrerAddress].x6Matrix[level].closedPart != address(0)) {
if ((users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] ==
users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]) &&
(users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] ==
users[referrerAddress].x6Matrix[level].closedPart)) {
updateX6(userAddress, referrerAddress, level, true);
return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
} else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] ==
users[referrerAddress].x6Matrix[level].closedPart) {
updateX6(userAddress, referrerAddress, level, true);
return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
} else {
updateX6(userAddress, referrerAddress, level, false);
return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
}
}
if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[1] == userAddress) {
updateX6(userAddress, referrerAddress, level, false);
return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
} else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == userAddress) {
updateX6(userAddress, referrerAddress, level, true);
return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
}
if ((users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] != users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]) &&
(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length <=
users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length)) {
updateX6(userAddress, referrerAddress, level, false);
} else {
updateX6(userAddress, referrerAddress, level, true);
}
updateX6ReferrerSecondLevel(userAddress, referrerAddress, level, _deadline, withPayment);
}
function updateX6(address userAddress, address referrerAddress, uint8 level, bool x2) internal {
if (!x2) {
users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.push(userAddress);
emit NewUserPlace(userAddress, users[referrerAddress].x6Matrix[level].firstLevelReferrals[0], 2, level, uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
emit NewUserPlace(userAddress, referrerAddress, 2, level, 2 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[0];
} else {
users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.push(userAddress);
emit NewUserPlace(userAddress, users[referrerAddress].x6Matrix[level].firstLevelReferrals[1], 2, level, uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
emit NewUserPlace(userAddress, referrerAddress, 2, level, 4 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[1];
}
}
function updateX6ReferrerSecondLevel(address userAddress, address referrerAddress, uint8 level, uint256 _deadline, bool withPayment) internal {
if (users[referrerAddress].x6Matrix[level].secondLevelReferrals.length < 4) {
sendERC20Dividends(referrerAddress, userAddress, 2, level, _deadline, withPayment);
return ;
}
address[] memory x6 = users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].firstLevelReferrals;
if (x6.length == 2) {
if (x6[0] == referrerAddress ||
x6[1] == referrerAddress) {
users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
} else if (x6.length == 1) {
if (x6[0] == referrerAddress) {
users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
}
}
}
users[referrerAddress].x6Matrix[level].firstLevelReferrals = new address[](0);
users[referrerAddress].x6Matrix[level].secondLevelReferrals = new address[](0);
users[referrerAddress].x6Matrix[level].closedPart = address(0);
if (!users[referrerAddress].activeX6Levels[level+1] && level != LAST_LEVEL) {
users[referrerAddress].x6Matrix[level].blocked = true;
}
users[referrerAddress].x6Matrix[level].reinvestCount++;
if (referrerAddress != owner) {
address freeReferrerAddress = findFreeX6Referrer(referrerAddress, level);
emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 2, level);
updateX6Referrer(referrerAddress, freeReferrerAddress, level, _deadline, withPayment);
} else {
emit Reinvest(owner, address(0), userAddress, 2, level);
sendERC20Dividends(owner, userAddress, 2, level, _deadline, withPayment);
}
}
function findFreeX3Referrer(address userAddress, uint8 level) public view returns(address) {
while (true) {
if (users[users[userAddress].referrer].activeX3Levels[level] &&
!users[users[userAddress].referrer].x3Matrix[level].blocked) {
return users[userAddress].referrer;
}
userAddress = users[userAddress].referrer;
}
}
function findFreeX6Referrer(address userAddress, uint8 level) public view returns(address) {
while (true) {
if (users[users[userAddress].referrer].activeX6Levels[level] &&
!users[users[userAddress].referrer].x6Matrix[level].blocked) {
return users[userAddress].referrer;
}
userAddress = users[userAddress].referrer;
}
}
function usersActiveX3Levels(address userAddress, uint8 level) external view returns(bool) {
return users[userAddress].activeX3Levels[level];
}
function usersActiveX6Levels(address userAddress, uint8 level) external view returns(bool) {
return users[userAddress].activeX6Levels[level];
}
function usersX3Matrix(address userAddress, uint8 level) external view returns(address, address[] memory, bool, uint256) {
return (users[userAddress].x3Matrix[level].currentReferrer,
users[userAddress].x3Matrix[level].referrals,
users[userAddress].x3Matrix[level].blocked,
users[userAddress].x3Matrix[level].estEarn);
}
function usersX6Matrix(address userAddress, uint8 level) external view returns(address, address[] memory, address[] memory, bool, address, uint256) {
return (users[userAddress].x6Matrix[level].currentReferrer,
users[userAddress].x6Matrix[level].firstLevelReferrals,
users[userAddress].x6Matrix[level].secondLevelReferrals,
users[userAddress].x6Matrix[level].blocked,
users[userAddress].x6Matrix[level].closedPart,
users[userAddress].x6Matrix[level].estEarn);
}
function isUserExists(address user) public view returns (bool) {
return (users[user].id != 0);
}
function findERC20Receiver(address userAddress, address _from, uint8 matrix, uint8 level) internal returns(address, bool) {
address receiver = userAddress;
bool isExtraDividends;
if (matrix == 1) {
while (true) {
if (users[receiver].x3Matrix[level].blocked) {
emit MissedERC20Receive(receiver, _from, 1, level);
isExtraDividends = true;
receiver = users[receiver].x3Matrix[level].currentReferrer;
} else {
return (receiver, isExtraDividends);
}
}
} else {
while (true) {
if (users[receiver].x6Matrix[level].blocked) {
emit MissedERC20Receive(receiver, _from, 2, level);
isExtraDividends = true;
receiver = users[receiver].x6Matrix[level].currentReferrer;
} else {
return (receiver, isExtraDividends);
}
}
}
}
function sendERC20Dividends(address userAddress, address _from, uint8 matrix, uint8 level, uint256 _deadline, bool withPayment) internal returns (uint256 minAmount) {
if (!withPayment) {
return 0;
}
(address receiver, bool isExtraDividends) = findERC20Receiver(userAddress, _from, matrix, level);
uint256 iAmt = levelPrice[level] * 10 / 100;
uint256 lPrice = levelPrice[level] - iAmt;
payable(investor).transfer(iAmt);
emit InvestorDividens(investor, matrix, level, iAmt);
minAmount = swap(uniswapRouter, tokenAddr, lPrice, receiver, _deadline);
if (matrix == 1) {
users[receiver].x3Matrix[level].estEarn += minAmount;
} else {
users[receiver].x6Matrix[level].estEarn += minAmount;
}
emit ERC20Dividens(receiver, matrix, level, levelPrice[level], minAmount);
stats[1] += levelPrice[level];
stats[2] += minAmount;
if (isExtraDividends) {
emit SentExtraERC20Dividends(_from, receiver, matrix, level);
}
}
}
contract Storage {
bytes32 private constant _IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
bytes32 private constant _OWNR_SLOT = 0x47e21bd924639e009830914fa04c527878b6aa0d3a9314aa3b88500716eb806b;
event Upgrade(address indexed implementation);
event ChangeOwner(address indexed owner);
modifier isOwner() {
address owner = _owner();
require(msg.sender == owner || address(0) == owner, "Storage: Not owner.");
_;
}
constructor(address _impl) public {
require(_IMPL_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1), "Storage: Invalid IMPL slot");
require(_OWNR_SLOT == bytes32(uint256(keccak256("storage.owner.slot")) - 1), "Storage: Invalid OWNR slot");
_upgrade(_impl);
_changeOwner(msg.sender);
}
function _upgrade(address _impl) public isOwner returns (bool) {
bytes32 slot = _IMPL_SLOT;
emit Upgrade(_impl);
assembly {
sstore(slot, _impl)
}
return true;
}
function _changeOwner(address _ownr) public isOwner returns (bool) {
bytes32 slot = _OWNR_SLOT;
emit ChangeOwner(_ownr);
assembly {
sstore(slot, _ownr)
}
return true;
}
function _implementation() public view returns (address _impl) {
bytes32 slot = _IMPL_SLOT;
assembly {
_impl := sload(slot)
}
}
function _owner() public view returns (address _ownr) {
bytes32 slot = _OWNR_SLOT;
assembly {
_ownr := sload(slot)
}
}
fallback() external payable {
address _impl = _implementation();
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), _impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}