Contract Name:
AvaxVaultV1
Contract Source Code:
File 1 of 1 : AvaxVaultV1
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.4;
contract AvaxVaultV1 {
using SafeMath for uint256;
using SafeMath for uint8;
uint256 public constant INVEST_MIN_AMOUNT = 5 ether;
uint256[] public REFERRAL_PERCENTS = [50, 30, 20];
uint256 public constant PROJECT_FEE = 50; //5%
uint256 public constant DEVELOPER_FEE = 50; //5%
uint256 public constant PERCENTS_DIVIDER = 1000;
uint256 public constant TIME_STEP = 1 days;
uint256 public constant MAX_HOLD_PERCENT = 15;
uint256 WITHDRAW_FEE = 100; //10%
uint256 public totalStaked;
uint256 public totalRefBonus;
uint256 public totalUsers;
struct Plan {
uint256 time;
uint256 percent;
}
Plan[] internal plans;
struct Deposit {
uint8 plan;
uint256 percent;
uint256 amount;
uint256 profit;
uint256 start;
uint256 finish;
}
struct User {
Deposit[] deposits;
uint256 checkpoint;
uint256 holdBonusCheckpoint;
address payable referrer;
uint256 referrals;
uint256 totalBonus;
uint256 withdrawn;
}
mapping(address => User) internal users;
uint256 public startUNIX;
address payable private projectWallet;
address payable private developerWallet;
event Newbie(address user);
event NewDeposit(
address indexed user,
uint8 plan,
uint256 percent,
uint256 amount,
uint256 profit,
uint256 start,
uint256 finish
);
event Withdrawn(address indexed user, uint256 amount);
event RefBonus(
address indexed referrer,
address indexed referral,
uint256 indexed level,
uint256 amount
);
constructor(
address payable _projectWallet,
address payable _developerWallet
) {
require(!isContract(_projectWallet));
projectWallet = _projectWallet;
developerWallet = _developerWallet;
startUNIX = block.timestamp.add(365 days);
plans.push(Plan(14, 80)); // 8% per day for 14 days (at the end, compounding)
plans.push(Plan(28, 70)); // 7% per day for 28 days (at the end, compounding)
}
function launch() public {
require(msg.sender == developerWallet);
startUNIX = block.timestamp;
}
function invest(address payable referrer, uint8 plan) public payable {
_invest(referrer, plan, payable(msg.sender), msg.value);
}
function _invest(
address payable referrer,
uint8 plan,
address payable sender,
uint256 value
) private {
require(value >= INVEST_MIN_AMOUNT);
require(plan < 6, "Invalid plan");
require(startUNIX < block.timestamp, "contract hasn`t started yet");
uint256 fee = value.mul(PROJECT_FEE).div(PERCENTS_DIVIDER);
projectWallet.transfer(fee);
uint256 developerFee = value.mul(DEVELOPER_FEE).div(PERCENTS_DIVIDER);
developerWallet.transfer(developerFee);
User storage user = users[sender];
if (user.referrer == address(0)) {
if (users[referrer].deposits.length > 0 && referrer != sender) {
user.referrer = referrer;
}
address upline = user.referrer;
for (uint256 i = 0; i < 3; i++) {
if (upline != address(0)) {
users[upline].referrals = users[upline].referrals.add(1);
upline = users[upline].referrer;
} else break;
}
}
if (user.referrer != address(0)) {
uint256 _refBonus = 0;
address payable upline = user.referrer;
for (uint256 i = 0; i < 3; i++) {
if (upline != address(0)) {
uint256 amount = value.mul(REFERRAL_PERCENTS[i]).div(
PERCENTS_DIVIDER
);
users[upline].totalBonus = users[upline].totalBonus.add(
amount
);
upline.transfer(amount);
_refBonus = _refBonus.add(amount);
emit RefBonus(upline, sender, i, amount);
upline = users[upline].referrer;
} else break;
}
totalRefBonus = totalRefBonus.add(_refBonus);
}
if (user.deposits.length == 0) {
user.checkpoint = block.timestamp;
user.holdBonusCheckpoint = block.timestamp;
emit Newbie(sender);
}
(uint256 percent, uint256 profit, uint256 finish) = getResult(
plan,
value
);
user.deposits.push(
Deposit(plan, percent, value, profit, block.timestamp, finish)
);
totalStaked = totalStaked.add(value);
totalUsers = totalUsers.add(1);
emit NewDeposit(
sender,
plan,
percent,
value,
profit,
block.timestamp,
finish
);
}
function withdraw() public {
User storage user = users[msg.sender];
uint256 totalAmount = getUserDividends(msg.sender);
require(totalAmount > 0, "User has no dividends");
uint256 contractBalance = address(this).balance;
if (contractBalance < totalAmount) {
totalAmount = contractBalance;
}
user.checkpoint = block.timestamp;
user.holdBonusCheckpoint = block.timestamp;
user.withdrawn = user.withdrawn.add(totalAmount);
payable(msg.sender).transfer(totalAmount);
emit Withdrawn(msg.sender, totalAmount);
}
function getContractBalance() public view returns (uint256) {
return address(this).balance;
}
function getPlanInfo(uint8 plan)
public
view
returns (uint256 time, uint256 percent)
{
time = plans[plan].time;
percent = plans[plan].percent;
}
function getPercent(uint8 plan) public view returns (uint256) {
return plans[plan].percent;
}
function getResult(uint8 plan, uint256 deposit)
public
view
returns (
uint256 percent,
uint256 profit,
uint256 finish
)
{
percent = getPercent(plan);
for (uint256 i = 0; i < plans[plan].time; i++) {
profit = profit.add(
(deposit.add(profit)).mul(percent).div(PERCENTS_DIVIDER)
);
}
finish = block.timestamp.add(plans[plan].time.mul(TIME_STEP));
}
function getUserPercentRate(address userAddress)
public
view
returns (uint256)
{
User storage user = users[userAddress];
uint256 timeMultiplier = block
.timestamp
.sub(user.holdBonusCheckpoint)
.div(TIME_STEP); // +0.1% per day
if (timeMultiplier > MAX_HOLD_PERCENT) {
timeMultiplier = MAX_HOLD_PERCENT;
}
return timeMultiplier;
}
function getUserDividends(address userAddress)
public
view
returns (uint256)
{
User storage user = users[userAddress];
uint256 totalAmount;
for (uint256 i = 0; i < user.deposits.length; i++) {
if (user.checkpoint < user.deposits[i].finish) {
if (block.timestamp > user.deposits[i].finish) {
uint256 _profit = user.deposits[i].profit;
uint256 _profitWithFee = _profit.sub(
_profit.mul(WITHDRAW_FEE).div(PERCENTS_DIVIDER)
);
totalAmount = totalAmount.add(_profitWithFee);
}
}
}
return totalAmount;
}
function getUserAvailable(address userAddress)
public
view
returns (uint256)
{
User storage user = users[userAddress];
uint256 totalAmount;
for (uint256 i = 0; i < user.deposits.length; i++) {
if (block.timestamp > user.deposits[i].finish) {
totalAmount = totalAmount.add(user.deposits[i].profit);
}
}
return totalAmount;
}
function getContractInfo()
public
view
returns (
uint256,
uint256,
uint256
)
{
return (totalStaked, totalRefBonus, totalUsers);
}
function getUserWithdrawn(address userAddress)
public
view
returns (uint256)
{
return users[userAddress].withdrawn;
}
function getUserCheckpoint(address userAddress)
public
view
returns (uint256)
{
return users[userAddress].checkpoint;
}
function getUserReferrer(address userAddress)
public
view
returns (address)
{
return users[userAddress].referrer;
}
function getUserDownlineCount(address userAddress)
public
view
returns (uint256)
{
return (users[userAddress].referrals);
}
function getUserReferralTotalBonus(address userAddress)
public
view
returns (uint256)
{
return users[userAddress].totalBonus;
}
function getUserDepositCount(address userAddress)
public
view
returns (uint256)
{
return users[userAddress].deposits.length;
}
function getUserTotalDeposits(address userAddress)
public
view
returns (uint256 amount)
{
for (uint256 i = 0; i < users[userAddress].deposits.length; i++) {
amount = amount.add(users[userAddress].deposits[i].amount);
}
}
function getUserTotalWithdrawn(address userAddress)
public
view
returns (uint256 amount)
{}
function getUserDepositInfo(address userAddress, uint256 index)
public
view
returns (
uint8 plan,
uint256 percent,
uint256 amount,
uint256 profit,
uint256 start,
uint256 finish
)
{
User storage user = users[userAddress];
plan = user.deposits[index].plan;
percent = user.deposits[index].percent;
amount = user.deposits[index].amount;
profit = user.deposits[index].profit;
start = user.deposits[index].start;
finish = user.deposits[index].finish;
}
function isContract(address addr) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(addr)
}
return size > 0;
}
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}