文件 1 的 1:Smartlevel.sol
pragma solidity ^0.5.11;
contract Smartlevel {
address public creator;
uint public currentUserID;
mapping(uint => uint) public levelPrice;
mapping(address => User) public users;
mapping(uint => address) public userAddresses;
uint MAX_LEVEL = 10;
uint REFERRALS_LIMIT = 3;
uint LEVEL_DURATION = 15 days;
struct User {
uint id;
uint referrerID;
address[] referrals;
mapping (uint => uint) levelExpiresAt;
}
event RegisterUserEvent(address indexed user, address indexed referrer, uint time, uint id, uint expires);
event BuyLevelEvent(address indexed user, uint indexed level, uint time, uint expires);
event GetLevelProfitEvent(address indexed user, address indexed referral, uint indexed level, uint time);
event LostLevelProfitEvent(address indexed user, address indexed referral, uint indexed level, uint time);
modifier userNotRegistered() {
require(users[msg.sender].id == 0, 'User is already registered');
_;
}
modifier userRegistered() {
require(users[msg.sender].id != 0, 'User does not exist');
_;
}
modifier validReferrerID(uint _referrerID) {
require(_referrerID > 0 && _referrerID <= currentUserID, 'Invalid referrer ID');
_;
}
modifier validLevel(uint _level) {
require(_level > 0 && _level <= MAX_LEVEL, 'Invalid level');
_;
}
modifier validLevelAmount(uint _level) {
require(msg.value == levelPrice[_level], 'Invalid level amount');
_;
}
constructor() public {
levelPrice[1] = 0.03 ether;
levelPrice[2] = 0.09 ether;
levelPrice[3] = 0.15 ether;
levelPrice[4] = 0.3 ether;
levelPrice[5] = 0.35 ether;
levelPrice[6] = 0.6 ether;
levelPrice[7] = 1 ether;
levelPrice[8] = 2 ether;
levelPrice[9] = 5 ether;
levelPrice[10] = 10 ether;
currentUserID++;
creator = 0x91c59276d6f1360BEB35e7e5105FE6A0BD26df2c;
users[creator] = createNewUser(0);
userAddresses[currentUserID] = creator;
for(uint i = 1; i <= MAX_LEVEL; i++) {
users[creator].levelExpiresAt[i] = 113131641600;
}
}
function() external payable {
uint level;
for(uint i = 1; i <= MAX_LEVEL; i++) {
if(msg.value == levelPrice[i]) {
level = i;
break;
}
}
require(level > 0, 'Invalid amount has sent');
if(users[msg.sender].id != 0) {
buyLevel(level);
return;
}
if(level != 1) {
revert('Buy first level for 0.03 ETH');
}
address referrer = bytesToAddress(msg.data);
registerUser(users[referrer].id);
}
function registerUser(uint _referrerID) public payable userNotRegistered() validReferrerID(_referrerID) validLevelAmount(1) {
if(users[userAddresses[_referrerID]].referrals.length >= REFERRALS_LIMIT) {
_referrerID = users[findReferrer(userAddresses[_referrerID])].id;
}
currentUserID++;
users[msg.sender] = createNewUser(_referrerID);
userAddresses[currentUserID] = msg.sender;
users[msg.sender].levelExpiresAt[1] = now + LEVEL_DURATION;
users[userAddresses[_referrerID]].referrals.push(msg.sender);
transferLevelPayment(1, msg.sender);
emit RegisterUserEvent(msg.sender, userAddresses[_referrerID], now, currentUserID, users[msg.sender].levelExpiresAt[1]);
}
function buyLevel(uint _level) public payable userRegistered() validLevel(_level) validLevelAmount(_level) {
for(uint l = _level - 1; l > 0; l--) {
require(getUserLevelExpiresAt(msg.sender, l) >= now, 'Buy the previous level');
}
if(getUserLevelExpiresAt(msg.sender, _level) < now) {
users[msg.sender].levelExpiresAt[_level] = now + LEVEL_DURATION;
} else {
users[msg.sender].levelExpiresAt[_level] += LEVEL_DURATION;
}
transferLevelPayment(_level, msg.sender);
emit BuyLevelEvent(msg.sender, _level, now, users[msg.sender].levelExpiresAt[_level]);
}
function findReferrer(address _user) public view returns(address) {
if(users[_user].referrals.length < REFERRALS_LIMIT) {
return _user;
}
address[1200] memory referrals;
referrals[0] = users[_user].referrals[0];
referrals[1] = users[_user].referrals[1];
referrals[2] = users[_user].referrals[2];
address referrer;
for(uint i = 0; i < 1200; i++) {
if(users[referrals[i]].referrals.length < REFERRALS_LIMIT) {
referrer = referrals[i];
break;
}
if(i >= 400) {
continue;
}
referrals[(i + 1) * 3] = users[referrals[i]].referrals[0];
referrals[(i + 1) * 3 + 1] = users[referrals[i]].referrals[1];
referrals[(i + 1) * 3 + 2] = users[referrals[i]].referrals[2];
}
require(referrer != address(0), 'Referrer was not found');
return referrer;
}
function transferLevelPayment(uint _level, address _user) internal {
uint height = _level % 2 == 0 ? 2 : 1;
address referrer = getUserUpline(_user, height);
if(referrer == address(0)) {
referrer = creator;
}
if(getUserLevelExpiresAt(referrer, _level) < now) {
emit LostLevelProfitEvent(referrer, msg.sender, _level, now);
transferLevelPayment(_level, referrer);
return;
}
if(addressToPayable(referrer).send(msg.value)) {
emit GetLevelProfitEvent(referrer, msg.sender, _level, now);
}
}
function getUserUpline(address _user, uint height) public view returns(address) {
if(height <= 0 || _user == address(0)) {
return _user;
}
return this.getUserUpline(userAddresses[users[_user].referrerID], height - 1);
}
function getUserReferrals(address _user) public view returns(address[] memory) {
return users[_user].referrals;
}
function getUserLevelExpiresAt(address _user, uint _level) public view returns(uint) {
return users[_user].levelExpiresAt[_level];
}
function createNewUser(uint _referrerID) private view returns(User memory) {
return User({ id: currentUserID, referrerID: _referrerID, referrals: new address[](0) });
}
function bytesToAddress(bytes memory _addr) private pure returns(address addr) {
assembly {
addr := mload(add(_addr, 20))
}
}
function addressToPayable(address _addr) private pure returns(address payable) {
return address(uint160(_addr));
}
}
{
"compilationTarget": {
"Smartlevel.sol": "Smartlevel"
},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}