文件 1 的 1:HoobiSocial.sol
pragma solidity >=0.4.0 <0.7.0;
interface IMember {
function addMember(address _member, address _parent) external;
function getParent(address _member) external view returns (address _parent);
function isMember(address _member) external view returns (bool);
function getParentTree(address _member) external view returns (address[8] memory);
function getRefs(address _member) external view returns (address[] memory);
function getRef(address _member, uint256 _index) external view returns (address);
function getRefsLength(address _member) external view returns (uint256);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
interface OldContract {
function getUser(address _address) external view returns (uint256 level, uint256[8] memory refTree, uint256 totalMember);
function getCurrentBonus() external view returns (uint256 step, uint256 max, uint256 sold, uint256 bonus);
}
contract Hoobi {
address private owner;
address private fund = 0x17796dB252B9FF3ddff9646C7E8738bF50e3e58e;
OldContract old = OldContract(0xb28F1760695d65e501966353831C286D6E26Ec10);
IERC20 share;
IMember member;
uint256 shareDecimal = 6;
uint256 priceETH = 200 * 10**6;
uint256 lastPriceETH = 200 * 10 ** 6;
uint256 priceShare = 10**5;
uint256[7] refPercent = [5, 4, 2, 1, 1, 1, 1];
uint256[3] firstPercent = [60, 80, 100];
uint256[3] secondPercent = [50, 60, 70];
uint256[9] bonusShare = [520, 380, 260, 140, 80, 50, 30, 20, 16];
uint256[9] poolShare = [
10**11,
3 * 10**11,
10**12,
3 * 10**12,
8 * 10**12,
20 * 10**12,
50 * 10**12,
100 * 10**12,
300 * 10**12
];
uint256[9] soldShare = [0, 0, 0, 0, 0, 0, 0, 0, 0];
uint256[3] level = [100 * 10**6, 200 * 10**6, 400 * 10**6];
uint256 currentPool = 0;
address bot = 0x2637F27ed1A8dC88a950b785329cc5606F7CaEa7;
struct User {
uint256 level;
uint256[8] refTree;
}
mapping(address => User) users;
modifier onlyOwner() {
require(msg.sender == owner, "Must be owner");
_;
}
modifier onlyMod() {
require(msg.sender == owner || msg.sender == bot, "Must be bot");
_;
}
constructor(
address _shareContract,
address _memberContract
) public {
owner = msg.sender;
share = IERC20(_shareContract);
member = IMember(_memberContract);
}
function init() public onlyOwner {
(,,soldShare[0],) = old.getCurrentBonus();
}
function recover(address[] memory oldUsers) public onlyOwner {
for(uint i=0;i<oldUsers.length;i++){
(users[oldUsers[i]].level,users[oldUsers[i]].refTree,) = old.getUser(oldUsers[i]);
}
}
function getAmountETH(uint256 _amount) public view returns (uint256) {
return ((_amount * 10**24) / priceETH);
}
function getAmountETHLevel(uint _level) public view returns(uint){
if(_level == 0) return 0;
if(_level == 1) return getAmountETH(100);
if(_level == 2) return getAmountETH(200);
if(_level == 3) return getAmountETH(400);
return 0;
}
function getLevel(uint _amount) public view returns(uint8 level,uint256 value){
if (_amount == ((100 * 10**24) / priceETH)) {
return(1,100 * 10 ** 6);
} else if (_amount == ((200 * 10**24) / priceETH)){
return(2,200 * 10 ** 6);
} else if (_amount == ((400 * 10**24) / priceETH)) {
return(3,400 * 10 ** 6);
} else if (_amount == ((100 * 10**24) / lastPriceETH)) {
return(1,100 * 10 ** 6);
} else if (_amount == ((200 * 10**24) / lastPriceETH)) {
return(2,200 * 10 ** 6);
} else if (_amount == ((400 * 10**24) / lastPriceETH)) {
return(4,400 * 10 ** 6);
} else {
return(0,0);
}
}
function invest(address _ref) public payable {
require(member.isMember(msg.sender) || member.isMember(_ref),"Must be valid");
(uint8 userLevel,uint256 value) = getLevel(msg.value);
require(userLevel > users[msg.sender].level, "User only can upgrade membership!");
sendFunds(fund, (msg.value * 15) / 1000, 0);
users[msg.sender].level = userLevel;
if (member.isMember(msg.sender)) {
reInvest(msg.sender, msg.value);
} else {
member.addMember(msg.sender, _ref);
addNewInvestor(_ref, msg.value, userLevel);
}
if (currentPool < 9) {
uint256 amountShare = (value * (10**shareDecimal)) / priceShare;
uint256 bonus;
if (poolShare[currentPool] - soldShare[currentPool] >= value) {
bonus = (amountShare * bonusShare[currentPool]) / 10;
soldShare[currentPool] += value;
if (soldShare[currentPool] == poolShare[currentPool])
currentPool++;
} else {
uint256 payed = poolShare[currentPool] - soldShare[currentPool];
bonus =
(((payed * (10**shareDecimal)) / priceShare) *
bonusShare[currentPool]) /
10;
soldShare[currentPool] = poolShare[currentPool];
currentPool++;
if (currentPool < 9) {
bonus +=
((((value - payed) * (10**shareDecimal)) / priceShare) *
bonusShare[currentPool]) /
10;
soldShare[currentPool] += value - payed;
}
}
sendFunds(msg.sender, amountShare + bonus, 1);
} else {
uint256 amountShare = (value * (10**shareDecimal)) / priceShare;
sendFunds(msg.sender, amountShare, 1);
}
}
function reInvest(address _investor, uint256 _value)
private
{
address[8] memory parentTree = member.getParentTree(_investor);
if (parentTree[0] != address(0x0)) {
sendFunds(parentTree[0],(_value * secondPercent[users[parentTree[0]].level - 1]) / 100,0);
for (uint256 i = 1; i < 8; i++) {
if (parentTree[i] == address(0x0)) {
break;
} else {
sendFunds(
parentTree[i],
(_value * refPercent[i - 1]) / 100,
0
);
}
}
}
}
function addNewInvestor(address _ref, uint256 _value, uint256 _level)
private
{
if(_ref != address(0x0)){
User storage user = users[_ref];
user.refTree[0] += 1;
if (user.refTree[0] == 2) {
if (user.level < _level) {
if(getAmountETHLevel(user.level) > 0 && user.level > 0){
sendFunds(_ref,(getAmountETHLevel(user.level) * firstPercent[user.level - 1]) /100,0);
}
} else {
sendFunds(_ref,(_value * firstPercent[user.level - 1]) / 100,0);
}
}
if (user.refTree[0] > 2) { sendFunds( _ref,(_value * secondPercent[user.level - 1]) / 100,0); }
address[8] memory parentTree = member.getParentTree(_ref);
for(uint i = 0;i < 7;i++){
if(parentTree[i] != address(0x0)){
uint256[8] storage userRef = users[parentTree[i]].refTree;
userRef[i+1] += 1;
if (userRef[i+1] == 2) {
sendFunds(parentTree[i], (_value * refPercent[i]) / 100, 0);
} else {
if (userRef[i+1] > 2) {
sendFunds(parentTree[i],(_value * refPercent[i]) / 200,0);
}
}
} else {
break;
}
}
}
}
function getUserStats(address _investor) public view returns(address[] memory refs){
address[] memory tempRefs = member.getRefs(_investor);
return (tempRefs);
}
function getUser(address _address)
public
view
returns (uint256 userLevel, uint256[8] memory refTree)
{
User memory user = users[_address];
return (user.level, user.refTree);
}
function getUserRefsStats(address _investor)
public
view
returns (address[] memory refs)
{
address[] memory _refs = member.getRefs(_investor);
return (_refs);
}
function getPrice()
public
view
returns (uint256 ethPrice, uint256 sharePrice)
{
return (priceETH, priceShare);
}
function getCurrentBonus()
public
view
returns (uint256 step, uint256 max, uint256 sold, uint256 bonus)
{
return (
currentPool,
poolShare[currentPool],
soldShare[currentPool],
bonusShare[currentPool]
);
}
function validRef(address _investor, address _ref)
public
view
returns (bool)
{
if (member.isMember(_investor)) {
return true;
} else {
if (member.isMember(_ref)) {
return true;
} else {
return false;
}
}
}
function changeMemberContract(address _contract) public onlyOwner {
member = IMember(_contract);
}
function changeShareContract(address _contract) public onlyOwner {
share = IERC20(_contract);
}
function changeETHPrice(uint256 _price) public onlyMod {
lastPriceETH = priceETH;
priceETH = _price;
}
function changeBot(address _bot) public onlyOwner {
bot = _bot;
}
function changeSharePrice(uint256 _price) public onlyMod {
priceShare = _price;
}
function adminWidthdraw(
address _address,
uint256 _amount,
uint256 _currency
) public onlyOwner {
sendFunds(_address, _amount, _currency);
}
function sendFunds(address beneficiary, uint256 amount, uint256 currency)
private
{
if (currency == 0) {
require(address(this).balance >= amount,"Balance in contract is not enough to cash out, please contact for admin");
address(uint160(beneficiary)).transfer(amount);
} else {
require(share.balanceOf(address(this)) >= amount,"Balance in contract is not enough to cash out, please contact for admin");
share.transfer(beneficiary, amount);
}
}
}