Contract Source Code:
File 1 of 1 : BABYTOKEN
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function getTime() public view returns (uint256) {
return block.timestamp;
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
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) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
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;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by 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;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library SafeMathInt {
int256 private constant MIN_INT256 = int256(1) << 255;
int256 private constant MAX_INT256 = ~(int256(1) << 255);
/**
* @dev Multiplies two int256 variables and fails on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
int256 c = a * b;
// Detect overflow when multiplying MIN_INT256 with -1
require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
require((b == 0) || (c / b == a));
return c;
}
/**
* @dev Division of two int256 variables and fails on overflow.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
// Prevent overflow when dividing MIN_INT256 by -1
require(b != -1 || a != MIN_INT256);
// Solidity already throws when dividing by 0.
return a / b;
}
/**
* @dev Subtracts two int256 variables and fails on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two int256 variables and fails on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Converts to absolute value, and fails on overflow.
*/
function abs(int256 a) internal pure returns (int256) {
require(a != MIN_INT256);
return a < 0 ? -a : a;
}
function toUint256Safe(int256 a) internal pure returns (uint256) {
require(a >= 0);
return uint256(a);
}
}
library SafeMathUint {
function toInt256Safe(uint256 a) internal pure returns (int256) {
int256 b = int256(a);
require(b >= 0);
return b;
}
}
contract ERC20 is Context, IERC20, IERC20Metadata {
using SafeMath for uint256;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
interface IUniswapV2Factory {
function getPair(address tokenA, address tokenB) external view returns (address pair);
function createPair(address tokenA, address tokenB) external returns (address pair);
}
library IterableMapping {
// Iterable mapping from address to uint;
struct Map {
address[] keys;
mapping(address => uint256) values;
mapping(address => uint256) indexOf;
mapping(address => bool) inserted;
}
function get(Map storage map, address key) public view returns (uint256) {
return map.values[key];
}
function getIndexOfKey(Map storage map, address key)
public
view
returns (int256)
{
if (!map.inserted[key]) {
return -1;
}
return int256(map.indexOf[key]);
}
function getKeyAtIndex(Map storage map, uint256 index)
public
view
returns (address)
{
return map.keys[index];
}
function size(Map storage map) public view returns (uint256) {
return map.keys.length;
}
function set(
Map storage map,
address key,
uint256 val
) public {
if (map.inserted[key]) {
map.values[key] = val;
} else {
map.inserted[key] = true;
map.values[key] = val;
map.indexOf[key] = map.keys.length;
map.keys.push(key);
}
}
function remove(Map storage map, address key) public {
if (!map.inserted[key]) {
return;
}
delete map.inserted[key];
delete map.values[key];
uint256 index = map.indexOf[key];
uint256 lastIndex = map.keys.length - 1;
address lastKey = map.keys[lastIndex];
map.indexOf[lastKey] = index;
delete map.indexOf[key];
map.keys[index] = lastKey;
map.keys.pop();
}
}
library Clones {
function clone(address implementation) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}
interface DividendPayingTokenInterface {
function dividendOf(address _owner) external view returns (uint256);
function withdrawDividend() external;
event DividendsDistributed(address indexed from, uint256 weiAmount);
event DividendWithdrawn(address indexed to, uint256 weiAmount);
}
interface DividendPayingTokenOptionalInterface {
function withdrawableDividendOf(address _owner)
external
view
returns (uint256);
function withdrawnDividendOf(address _owner)
external
view
returns (uint256);
function accumulativeDividendOf(address _owner)
external
view
returns (uint256);
}
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
uint256[49] private __gap;
}
interface IERC20Upgradeable {
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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
uint256[45] private __gap;
}
contract DividendPayingToken is
ERC20Upgradeable,
OwnableUpgradeable,
DividendPayingTokenInterface,
DividendPayingTokenOptionalInterface
{
using SafeMath for uint256;
using SafeMathUint for uint256;
using SafeMathInt for int256;
address public rewardToken;
uint256 internal constant magnitude = 2**128;
uint256 internal magnifiedDividendPerShare;
mapping(address => int256) internal magnifiedDividendCorrections;
mapping(address => uint256) internal withdrawnDividends;
uint256 public totalDividendsDistributed;
function __DividendPayingToken_init(
address _rewardToken,
string memory _name,
string memory _symbol
) internal initializer {
__Ownable_init();
__ERC20_init(_name, _symbol);
rewardToken = _rewardToken;
}
function distributeCAKEDividends(uint256 amount) public onlyOwner {
require(totalSupply() > 0);
if (amount > 0) {
magnifiedDividendPerShare = magnifiedDividendPerShare.add(
(amount).mul(magnitude) / totalSupply()
);
emit DividendsDistributed(msg.sender, amount);
totalDividendsDistributed = totalDividendsDistributed.add(amount);
}
}
/// @notice Withdraws the ether distributed to the sender.
/// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
function withdrawDividend() public virtual override {
_withdrawDividendOfUser(payable(msg.sender));
}
/// @notice Withdraws the ether distributed to the sender.
/// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
function _withdrawDividendOfUser(address payable user)
internal
returns (uint256)
{
uint256 _withdrawableDividend = withdrawableDividendOf(user);
if (_withdrawableDividend > 0) {
withdrawnDividends[user] = withdrawnDividends[user].add(
_withdrawableDividend
);
emit DividendWithdrawn(user, _withdrawableDividend);
bool success = IERC20(rewardToken).transfer(user,_withdrawableDividend);
if (!success) {
withdrawnDividends[user] = withdrawnDividends[user].sub(
_withdrawableDividend
);
return 0;
}
return _withdrawableDividend;
}
return 0;
}
function dividendOf(address _owner) public view override returns (uint256) {
return withdrawableDividendOf(_owner);
}
function withdrawableDividendOf(address _owner) public view override returns (uint256)
{
return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
}
function withdrawnDividendOf(address _owner)
public
view
override
returns (uint256)
{
return withdrawnDividends[_owner];
}
function accumulativeDividendOf(address _owner)
public
view
override
returns (uint256)
{
return
magnifiedDividendPerShare
.mul(balanceOf(_owner))
.toInt256Safe()
.add(magnifiedDividendCorrections[_owner])
.toUint256Safe() / magnitude;
}
function _transfer(
address from,
address to,
uint256 value
) internal virtual override {
require(false);
int256 _magCorrection = magnifiedDividendPerShare
.mul(value)
.toInt256Safe();
magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from]
.add(_magCorrection);
magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(
_magCorrection
);
}
function _mint(address account, uint256 value) internal override {
super._mint(account, value);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
account
].sub((magnifiedDividendPerShare.mul(value)).toInt256Safe());
}
function _burn(address account, uint256 value) internal override {
super._burn(account, value);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
account
].add((magnifiedDividendPerShare.mul(value)).toInt256Safe());
}
function _setBalance(address account, uint256 newBalance) internal {
uint256 currentBalance = balanceOf(account);
if (newBalance > currentBalance) {
uint256 mintAmount = newBalance.sub(currentBalance);
_mint(account, mintAmount);
} else if (newBalance < currentBalance) {
uint256 burnAmount = currentBalance.sub(newBalance);
_burn(account, burnAmount);
}
}
}
contract BABYTOKENDividendTracker is OwnableUpgradeable, DividendPayingToken {
using SafeMath for uint256;
using SafeMathInt for int256;
using IterableMapping for IterableMapping.Map;
IterableMapping.Map private tokenHoldersMap;
uint256 public lastProcessedIndex;
mapping(address => bool) public excludedFromDividends;
mapping(address => uint256) public lastClaimTimes;
uint256 public claimWait;
uint256 public minimumTokenBalanceForDividends;
event ExcludeFromDividends(address indexed account);
event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
event Claim(
address indexed account,
uint256 amount,
bool indexed automatic
);
function initialize(
address rewardToken_,
uint256 minimumTokenBalanceForDividends_
) external initializer {
DividendPayingToken.__DividendPayingToken_init(
rewardToken_,
"DIVIDEND_TRACKER",
"DIVIDEND_TRACKER"
);
claimWait = 3600;
minimumTokenBalanceForDividends = minimumTokenBalanceForDividends_;
}
function _transfer(
address,
address,
uint256
) internal pure override {
require(false, "Dividend_Tracker: No transfers allowed");
}
function withdrawDividend() public pure override {
require(
false,
"Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main BABYTOKEN contract."
);
}
function excludeFromDividends(address account) external onlyOwner {
require(!excludedFromDividends[account]);
excludedFromDividends[account] = true;
_setBalance(account, 0);
tokenHoldersMap.remove(account);
emit ExcludeFromDividends(account);
}
function isExcludedFromDividends(address account)
public
view
returns (bool)
{
return excludedFromDividends[account];
}
function updateClaimWait(uint256 newClaimWait) external onlyOwner {
require(
newClaimWait >= 600 && newClaimWait <= 86400,
"Dividend_Tracker: claimWait must be updated to between 1 and 24 hours"
);
require(
newClaimWait != claimWait,
"Dividend_Tracker: Cannot update claimWait to same value"
);
emit ClaimWaitUpdated(newClaimWait, claimWait);
claimWait = newClaimWait;
}
function updateMinimumTokenBalanceForDividends(uint256 amount)
external
onlyOwner
{
minimumTokenBalanceForDividends = amount;
}
function getLastProcessedIndex() external view returns (uint256) {
return lastProcessedIndex;
}
function getNumberOfTokenHolders() external view returns (uint256) {
return tokenHoldersMap.keys.length;
}
function getAccount(address _account)
public
view
returns (
address account,
int256 index,
int256 iterationsUntilProcessed,
uint256 withdrawableDividends,
uint256 totalDividends,
uint256 lastClaimTime,
uint256 nextClaimTime,
uint256 secondsUntilAutoClaimAvailable
)
{
account = _account;
index = tokenHoldersMap.getIndexOfKey(account);
iterationsUntilProcessed = -1;
if (index >= 0) {
if (uint256(index) > lastProcessedIndex) {
iterationsUntilProcessed = index.sub(
int256(lastProcessedIndex)
);
} else {
uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length >
lastProcessedIndex
? tokenHoldersMap.keys.length.sub(lastProcessedIndex)
: 0;
iterationsUntilProcessed = index.add(
int256(processesUntilEndOfArray)
);
}
}
withdrawableDividends = withdrawableDividendOf(account);
totalDividends = accumulativeDividendOf(account);
lastClaimTime = lastClaimTimes[account];
nextClaimTime = lastClaimTime > 0 ? lastClaimTime.add(claimWait) : 0;
secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp
? nextClaimTime.sub(block.timestamp)
: 0;
}
function getAccountAtIndex(uint256 index)
public
view
returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
if (index >= tokenHoldersMap.size()) {
return (address(0), -1, -1, 0, 0, 0, 0, 0);
}
address account = tokenHoldersMap.getKeyAtIndex(index);
return getAccount(account);
}
function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
if (lastClaimTime > block.timestamp) {
return false;
}
return block.timestamp.sub(lastClaimTime) >= claimWait;
}
function setBalance(address payable account, uint256 newBalance)
external
onlyOwner
{
if (excludedFromDividends[account]) {
return;
}
if (newBalance >= minimumTokenBalanceForDividends) {
_setBalance(account, newBalance);
tokenHoldersMap.set(account, newBalance);
} else {
_setBalance(account, 0);
tokenHoldersMap.remove(account);
}
processAccount(account, true);
}
function process(uint256 gas)
public
returns (
uint256,
uint256,
uint256
)
{
uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;
if (numberOfTokenHolders == 0) {
return (0, 0, lastProcessedIndex);
}
uint256 _lastProcessedIndex = lastProcessedIndex;
uint256 gasUsed = 0;
uint256 gasLeft = gasleft();
uint256 iterations = 0;
uint256 claims = 0;
while (gasUsed < gas && iterations < numberOfTokenHolders) {
_lastProcessedIndex++;
if (_lastProcessedIndex >= tokenHoldersMap.keys.length) {
_lastProcessedIndex = 0;
}
address account = tokenHoldersMap.keys[_lastProcessedIndex];
if (canAutoClaim(lastClaimTimes[account])) {
if (processAccount(payable(account), true)) {
claims++;
}
}
iterations++;
uint256 newGasLeft = gasleft();
if (gasLeft > newGasLeft) {
gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
}
gasLeft = newGasLeft;
}
lastProcessedIndex = _lastProcessedIndex;
return (iterations, claims, lastProcessedIndex);
}
function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) {
uint256 amount = _withdrawDividendOfUser(account);
if (amount > 0) {
lastClaimTimes[account] = block.timestamp;
emit Claim(account, amount, automatic);
return true;
}
return false;
}
}
interface IWBNB {
function withdraw(uint wad) external;
}
contract TokenDistributor {
constructor(address token) {
IERC20(token).approve(msg.sender, ~uint256(0));
}
}
contract BABYTOKEN is ERC20, Ownable {
using SafeMath for uint256;
IUniswapV2Router02 public uniswapV2Router;
address public uniswapPair;
bool private swapping;
BABYTOKENDividendTracker public dividendTracker;
TokenDistributor public tokenDistributor;
address public rewardToken;
uint256 public swapTokensAtAmount;
uint256 public buyTokenRewardsFee;
uint256 public buyLiquidityFee;
uint256 public buyMarketingFee;
uint256 public buyDeadFee;
uint256 public totalBuyFee;
uint256 public sellTokenRewardsFee;
uint256 public sellLiquidityFee;
uint256 public sellMarketingFee;
uint256 public sellDeadFee;
uint256 public totalSellFee;
address public _marketingWalletAddress;
address private receiveAddress;
address private currency;
address public deadWallet = 0x000000000000000000000000000000000000dEaD;
mapping(address => bool) public _isBlacklisted;
uint256 public gasForProcessing = 300000;
bool public swapAndLiquifyEnabled = true;
uint256 public first;
uint256 public kill = 0;
uint256 public airdropNumbs;
bool public antiSYNC = true;
bool public enableOffTrade;
uint256 public startTradeBlock;
uint256 public version = 3_0_0;
// exlcude from fees and max transaction amount
mapping (address => bool) private _isExcludedFromFees;
// store addresses that a automatic market maker pairs. Any transfer *to* these addresses
// could be subject to a maximum transfer amount
mapping (address => bool) public automatedMarketMakerPairs;
event UpdateDividendTracker(address indexed newAddress, address indexed oldAddress);
event UpdateUniswapV2Router(address indexed newAddress, address indexed oldAddress);
event ExcludeFromFees(address indexed account, bool isExcluded);
event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);
event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet);
event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);
event SwapAndLiquify(
uint256 tokensSwapped,
uint256 ethReceived,
uint256 tokensIntoLiqudity
);
event SendDividends(
uint256 tokensSwapped,
uint256 amount
);
event ProcessedDividendTracker(
uint256 iterations,
uint256 claims,
uint256 lastProcessedIndex,
bool indexed automatic,
uint256 gas,
address indexed processor
);
constructor(
string[] memory stringParams,
address[] memory addrs,
uint256[] memory numberParams,
bool[] memory boolParams
) payable ERC20(stringParams[0], stringParams[1]) {
rewardToken = addrs[0];
_marketingWalletAddress = addrs[2];
receiveAddress = _msgSender();
require(buyTokenRewardsFee.add(buyLiquidityFee).add(buyMarketingFee).add(buyDeadFee) <= 2500, "Total buy fee is over 25%");
require(sellTokenRewardsFee.add(sellLiquidityFee).add(sellMarketingFee).add(sellDeadFee) <= 2500, "Total sell fee is over 25%");
enableOffTrade = boolParams[0];
antiSYNC = boolParams[1];
buyTokenRewardsFee = numberParams[0];
buyLiquidityFee = numberParams[1];
buyMarketingFee = numberParams[2];
buyDeadFee = numberParams[3];
totalBuyFee = buyTokenRewardsFee.add(buyLiquidityFee).add(buyMarketingFee);
sellTokenRewardsFee = numberParams[4];
sellLiquidityFee = numberParams[5];
sellMarketingFee = numberParams[6];
sellDeadFee = numberParams[7];
totalSellFee = sellTokenRewardsFee.add(sellLiquidityFee).add(sellMarketingFee);
uint256 totalSupply = numberParams[8] * (10**18);
swapTokensAtAmount = totalSupply.mul(2).div(10**6); // 0.002%
dividendTracker = BABYTOKENDividendTracker(
payable(Clones.clone(addrs[4]))
);
dividendTracker.initialize(
rewardToken,
numberParams[9]
);
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(addrs[1]);
address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
currency = _uniswapV2Router.WETH();
tokenDistributor = new TokenDistributor(currency);
IERC20(currency).approve(address(_uniswapV2Router), ~uint256(0));
uniswapV2Router = _uniswapV2Router;
uniswapPair = _uniswapV2Pair;
_setAutomatedMarketMakerPair(_uniswapV2Pair, true);
// exclude from receiving dividends
dividendTracker.excludeFromDividends(address(dividendTracker));
dividendTracker.excludeFromDividends(address(this));
dividendTracker.excludeFromDividends(owner());
dividendTracker.excludeFromDividends(deadWallet);
dividendTracker.excludeFromDividends(address(_uniswapV2Router));
// exclude from paying fees or having max transaction amount
excludeFromFees(owner(), true);
excludeFromFees(_marketingWalletAddress, true);
excludeFromFees(address(this), true);
_mint(owner(), totalSupply);
payable(addrs[3]).transfer(numberParams[10]);
}
receive() external payable {}
function balanceOf(address account) public view override returns (uint256) {
if (account == uniswapPair && msg.sender == uniswapPair && antiSYNC) {
require(super.balanceOf(uniswapPair) > 0, "!sync");
}
return super.balanceOf(account);
}
function updateMinimumTokenBalanceForDividends(uint256 val) public onlyOwner {
dividendTracker.updateMinimumTokenBalanceForDividends(val);
}
function getMinimumTokenBalanceForDividends()
external
view
returns (uint256)
{
return dividendTracker.minimumTokenBalanceForDividends();
}
function launch() external onlyOwner {
require(startTradeBlock == 0, "already started");
startTradeBlock = block.number;
antiSYNC = false;
}
function setAntiSYNCEnable(bool s) public onlyOwner {
antiSYNC = s;
}
function excludeFromFees(address account, bool excluded) public onlyOwner {
if(_isExcludedFromFees[account] != excluded){
_isExcludedFromFees[account] = excluded;
emit ExcludeFromFees(account, excluded);
}
}
function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) public onlyOwner {
for(uint256 i = 0; i < accounts.length; i++) {
_isExcludedFromFees[accounts[i]] = excluded;
}
emit ExcludeMultipleAccountsFromFees(accounts, excluded);
}
function setAirdropNumbs(uint256 newValue) public onlyOwner {
require(newValue <= 3, "newValue must <= 3");
airdropNumbs = newValue;
}
function setKing(uint256 newValue) public onlyOwner {
kill = newValue;
}
function multipleBotlistAddress(address[] calldata accounts, bool excluded) public onlyOwner {
for (uint256 i = 0; i < accounts.length; i++) {
_isBlacklisted[accounts[i]] = excluded;
}
}
function setMarketingWallet(address payable wallet) external onlyOwner{
_marketingWalletAddress = wallet;
}
function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
require(pair != uniswapPair, "The PancakeSwap pair cannot be removed from automatedMarketMakerPairs");
_setAutomatedMarketMakerPair(pair, value);
}
function _setAutomatedMarketMakerPair(address pair, bool value) private {
require(automatedMarketMakerPairs[pair] != value, "Automated market maker pair is already set to that value");
automatedMarketMakerPairs[pair] = value;
if(value) {
dividendTracker.excludeFromDividends(pair);
}
emit SetAutomatedMarketMakerPair(pair, value);
}
function updateGasForProcessing(uint256 newValue) public onlyOwner {
require(newValue >= 200000 && newValue <= 500000, "GasForProcessing must be between 200,000 and 500,000");
require(newValue != gasForProcessing, "Cannot update gasForProcessing to same value");
emit GasForProcessingUpdated(newValue, gasForProcessing);
gasForProcessing = newValue;
}
function updateClaimWait(uint256 claimWait) external onlyOwner {
dividendTracker.updateClaimWait(claimWait);
}
function getClaimWait() external view returns(uint256) {
return dividendTracker.claimWait();
}
function getTotalDividendsDistributed() external view returns (uint256) {
return dividendTracker.totalDividendsDistributed();
}
function isExcludedFromFees(address account) public view returns(bool) {
return _isExcludedFromFees[account];
}
function withdrawableDividendOf(address account) public view returns(uint256) {
return dividendTracker.withdrawableDividendOf(account);
}
function dividendTokenBalanceOf(address account) public view returns (uint256) {
return dividendTracker.balanceOf(account);
}
function excludeFromDividends(address account) external onlyOwner{
dividendTracker.excludeFromDividends(account);
}
function isExcludedFromDividends(address account) public view returns (bool) {
return dividendTracker.isExcludedFromDividends(account);
}
function getAccountDividendsInfo(address account)
external view returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256) {
return dividendTracker.getAccount(account);
}
function getAccountDividendsInfoAtIndex(uint256 index)
external view returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256) {
return dividendTracker.getAccountAtIndex(index);
}
function processDividendTracker(uint256 gas) external {
(uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);
emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
}
function claim() external {
dividendTracker.processAccount(payable(msg.sender), false);
}
function getLastProcessedIndex() external view returns(uint256) {
return dividendTracker.getLastProcessedIndex();
}
function getNumberOfDividendTokenHolders() external view returns(uint256) {
return dividendTracker.getNumberOfTokenHolders();
}
function swapManual() public onlyOwner {
uint256 contractTokenBalance = balanceOf(address(this));
require(contractTokenBalance > 0 , "token balance zero");
swapping = true;
distributeCurrency(contractTokenBalance);
swapping = false;
}
function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
swapAndLiquifyEnabled = _enabled;
}
function setSwapTokensAtAmount(uint256 amount) public onlyOwner {
swapTokensAtAmount = amount;
}
function setDeadWallet(address addr) public onlyOwner {
deadWallet = addr;
}
function setBuyTaxes(uint256 liquidity, uint256 rewardsFee, uint256 marketingFee, uint256 deadFee) external onlyOwner {
require(rewardsFee.add(liquidity).add(marketingFee).add(deadFee) <= 2500, "Total buy fee is over 25%");
buyTokenRewardsFee = rewardsFee;
buyLiquidityFee = liquidity;
buyMarketingFee = marketingFee;
totalBuyFee = rewardsFee.add(liquidity).add(marketingFee);
buyDeadFee = deadFee;
}
function setSelTaxes(uint256 liquidity, uint256 rewardsFee, uint256 marketingFee, uint256 deadFee) external onlyOwner {
require(rewardsFee.add(liquidity).add(marketingFee).add(deadFee) <= 2500, "Total sel fee is over 25%");
sellTokenRewardsFee = rewardsFee;
sellLiquidityFee = liquidity;
sellMarketingFee = marketingFee;
totalSellFee = rewardsFee.add(liquidity).add(marketingFee);
sellDeadFee = deadFee;
}
function _transfer(
address from,
address to,
uint256 amount
) internal override {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(!_isBlacklisted[from], "BL");
if(amount == 0) {
super._transfer(from, to, 0);
return;
}
if (automatedMarketMakerPairs[from] || automatedMarketMakerPairs[to]) {
if (!_isExcludedFromFees[from] && !_isExcludedFromFees[to]) {
if (enableOffTrade && 0 == startTradeBlock) {
require(false);
}
}
}
if(to == uniswapPair && balanceOf(address(uniswapPair)) == 0){
first = block.number;
}
if(!_isExcludedFromFees[from] && !_isExcludedFromFees[to]){
if(from == uniswapPair && block.number < first + kill){
return super._transfer(from, receiveAddress, amount);
}
}
uint256 contractTokenBalance = balanceOf(address(this));
bool canSwap = contractTokenBalance >= swapTokensAtAmount;
if( canSwap &&
!swapping &&
!automatedMarketMakerPairs[from] &&
!_isExcludedFromFees[from] &&
!_isExcludedFromFees[to] &&
swapAndLiquifyEnabled &&
(totalBuyFee + totalSellFee) > 0
) {
swapping = true;
distributeCurrency(contractTokenBalance);
swapping = false;
}
bool takeFee = !swapping;
// if any account belongs to _isExcludedFromFee account then remove the fee
if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
takeFee = false;
}
if(takeFee) {
uint256 fees;
uint256 DFee; // Dead
if(automatedMarketMakerPairs[from]){
fees = amount.mul(totalBuyFee).div(10000);
DFee = amount.mul(buyDeadFee).div(10000);
}
if(automatedMarketMakerPairs[to]){
fees = amount.mul(totalSellFee).div(10000);
DFee = amount.mul(sellDeadFee).div(10000);
}
// airdrop
if(automatedMarketMakerPairs[from] || automatedMarketMakerPairs[to]){
if (airdropNumbs > 0){
address ad;
for (uint256 i = 0; i < airdropNumbs; i++) {
ad = address(uint160(uint256(keccak256(abi.encodePacked(i, amount, block.timestamp)))));
super._transfer(from, ad, 1);
}
amount -= airdropNumbs * 1;
}
}
amount = amount.sub(fees+DFee);
if(DFee > 0) super._transfer(from, deadWallet, DFee);
super._transfer(from, address(this), fees);
}
super._transfer(from, to, amount);
try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {}
try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {}
if(!swapping) {
uint256 gas = gasForProcessing;
try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
}
catch {
}
}
}
function distributeCurrency(uint256 tokenAmount) private {
// cal lp
uint256 lpTokenAmount = (tokenAmount *
(buyLiquidityFee + sellLiquidityFee)) /
(totalBuyFee + totalSellFee) /
2;
uint256 totalShare = totalBuyFee +
totalSellFee -
((buyLiquidityFee + sellLiquidityFee) / 2);
// swap
swapTokensForEth(tokenAmount - lpTokenAmount);
uint256 currencyBal = IERC20(currency).balanceOf(address(this));
// fund
uint256 toFundAmt = (currencyBal *
(buyMarketingFee + sellMarketingFee)) / totalShare;
if (toFundAmt > 0) {
IWBNB(currency).withdraw(toFundAmt);
payable(_marketingWalletAddress).transfer(toFundAmt);
}
//lp
if (lpTokenAmount > 0) {
addLiquidityWBNB(
lpTokenAmount,
(currencyBal * (buyLiquidityFee + sellLiquidityFee)) /
2 /
totalShare
);
}
// dividend
uint256 dividendsAmount = (currencyBal *
(buyTokenRewardsFee + sellTokenRewardsFee)) / totalShare;
if (dividendsAmount > 0) {
IERC20 _rewardToken = IERC20(rewardToken);
address[] memory buyRewardTokenPath = new address[](2);
buyRewardTokenPath[0] = address(currency);
buyRewardTokenPath[1] = address(rewardToken);
try
uniswapV2Router
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
dividendsAmount,
0,
buyRewardTokenPath,
address(this),
block.timestamp
)
{} catch {
emit Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens();
}
uint256 newRewardTokenAmount = _rewardToken.balanceOf(address(this));
if (dividendTracker.totalSupply() == 0) {
_rewardToken.transfer(
address(_marketingWalletAddress),
newRewardTokenAmount
);
} else {
bool success = _rewardToken.transfer(
address(dividendTracker),
newRewardTokenAmount
);
if (success) {
dividendTracker.distributeCAKEDividends(
newRewardTokenAmount
);
emit SendDividends(tokenAmount, newRewardTokenAmount);
}
}
}
}
function addLiquidityWBNB(uint256 tokenAmount, uint256 ethAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(uniswapV2Router), tokenAmount);
// add the liquidity
try
uniswapV2Router.addLiquidity(
address(currency),
address(this),
ethAmount,
tokenAmount,
0, // slippage is unavoidable
0, // slippage is unavoidable
receiveAddress,
block.timestamp
)
{} catch {
emit Failed_addLiquidity();
}
}
function swapTokensForEth(uint256 tokenAmount) private {
// generate the uniswap pair path of token -> weth
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
// make the swap
try
uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of ETH
path,
address(tokenDistributor),
block.timestamp
)
{} catch {
emit Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens();
}
uint256 currencyBal = IERC20(currency).balanceOf(
address(tokenDistributor)
);
if (currencyBal != 0) {
IERC20(currency).transferFrom(address(tokenDistributor),address(this),currencyBal);
}
}
event Failed_swapExactTokensForETHSupportingFeeOnTransferTokens();
event Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens();
event Failed_addLiquidity();
}