TAMA - SHIBBY

Created Diff never expires
109 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
623 lines
66 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
586 lines
// SPDX-License-Identifier: Unlicensed
// SPDX-License-Identifier: Unlicensed
pragma experimental ABIEncoderV2;
pragma experimental ABIEncoderV2;
pragma solidity ^0.8.2;
pragma solidity ^0.8.2;


import '@openzeppelin/contracts/contracts/utils/Address.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/contracts/utils/Context.sol';
import '@openzeppelin/contracts/utils/Context.sol';
import '@openzeppelin/contracts/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/contracts/utils/math/SafeMath.sol';
import '@openzeppelin/contracts/utils/math/SafeMath.sol';


import './interfaces/IPancakeFactory.sol';
import './interfaces/IPancakeFactory.sol';
import './interfaces/IPancakePair.sol';
import './interfaces/IPancakePair.sol';
import './interfaces/IPancakeRouter02.sol';
import './interfaces/IPancakeRouter02.sol';




/**
/**
TAMARIN is an improved fork of SAFEMOON

SHIBBY is an improved fork of SAFEMOON


All functional issues identified in the certik.org SAFEMOON audit have been fixed
All functional issues identified in the certik.org SAFEMOON audit have been fixed
https://www.certik.org/projects/safemoon#
https://www.certik.org/projects/safemoon#


Upgrades:
1. Liquidity added automatically on swap sends LP tokens to the deadbeef address
(Addresses SSL-04)
2. A new method to market buy the token with BNB in the contract and burn it has been added. This adds increasing deflation.
(Addresses SSL-03)
3. A new method to zap contract tokens into liquidity has been added. If not called, then the above function places
deflationary pressure on TAMA by monotonically increasing contract balance of TAMA.
4. A new method, adminRescueTokens, has been added to rescue any tokens other than WBNB or TAMA sent to this contract.
If the contract contains WBNB or TAMA, then the final destination of those should be in liquidity
5. Deliver removed
(Addresses SSL-12)
6. A new charity fee has been added to the contract, which send a % of transactions to a (4/5) charity multisig (with majority public members)
These funds will be used solely for charity and allocated by the desire of the community
7. Upper bounds have been added to all fees, for a theoretical max fee of 10% (expected to be lower):
Max Charity Fee: 2%
Max Redistribution Fee: 3%
Max Liquidity Fee: 5%
8. The LP address and long term charity vaults will be excluded from rewards.

Comments on audit:
SSL-13:
Ownership will be transferred to a min-24hr TimelockController whose sole proposer is the multisig
#TAMARIN features (subject to change before launch):
3% fee auto add to the liquidity pool to be locked forever when selling
1% fee auto distribute to all holders
2% fee to a (4/5) charity multisig, which can release funds discretionally to charity with community input

DX Sale Allocation (49%)
Non-pool Supply Allocations (51%):
Burn (37%)
Team (2%)
0.25% unvested, to pay for design, marketing, and any other relevant expenses
0.75% vested (1 Year timelock)
1% vested (2 year timelock)
Charity Distributions (11%)
2% of the supply sent to multisig for short-term community charity + airdrops
2% of the supply sent to Binance Charity timelock (10 years)
3% of the supply sent to Binance Charity timelock (25 years)
5% of the supply sent to Binance Charity timelock (50 years)


Binance Charity
https://www.binance.charity/binance-charity-wallet/donate-anonymously
0x8b99f3660622e21f2910ecca7fbe51d654a1517d
*/
*/


contract Tamarin is Context, IERC20, Ownable {
contract ShibbyToken is Context, IERC20, Ownable {
using SafeMath for uint256;
using SafeMath for uint256;
using Address for address;
using Address for address;


mapping (address => uint256) private _rOwned;
mapping (address => uint256) private _rOwned;
mapping (address => uint256) private _tOwned;
mapping (address => uint256) private _tOwned;
mapping (address => mapping (address => uint256)) private _allowances;
mapping (address => mapping (address => uint256)) private _allowances;


mapping (address => bool) private _isExcludedFromFee;
mapping (address => bool) private _isExcludedFromFee;


mapping (address => bool) private _isExcluded;
mapping (address => bool) private _isExcluded;
address[] private _excluded;
address[] private _excluded;

uint256 private constant MAX = type(uint256).max;
uint256 private constant MAX = type(uint256).max;
uint256 private constant _tTotal = 1000000000 * 10**6 * 10**9;
uint256 private constant _tTotal = 1000000000 * 10**6 * 10**9;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _tFeeTotal;
uint256 private _tFeeTotal;


// https://gnosis-safe.binance.org/#/safes/0xD766ea4836cBfA926529b21A8396f1A326459c47/balances
// https://gnosis-safe.binance.org/#/safes/0x470b69f05D2C70736337F839944CD6B2692450c5/balances
address constant internal CHARITY_MULTISIG = 0xD766ea4836cBfA926529b21A8396f1A326459c47;
address constant internal CHARITY_DAO = 0x470b69f05D2C70736337F839944CD6B2692450c5;
address constant internal BURN_ADDRESS = 0xDEADbEeF000000000000000000000000DeaDbeEf;
address constant internal BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;


string private constant _name = "Tamarin";
string private constant _name = "Shibby";
string private constant _symbol = "TAMA";
string private constant _symbol = "SHIBBY";
uint8 private constant _decimals = 9;
uint8 private constant _decimals = 9;


uint256 public _maxCharityFee = 2;
uint256 public _maxCharityFee = 2;
uint256 public _charityFee = 1;
uint256 public _charityFee = 1;
uint256 private _previousCharityFee = _charityFee;
uint256 private _previousCharityFee = _charityFee;

uint256 public _maxTaxFee = 3;
uint256 public _maxTaxFee = 4;
uint256 public _taxFee = 3;
uint256 public _taxFee = 4;
uint256 private _previousTaxFee = _taxFee;
uint256 private _previousTaxFee = _taxFee;

uint256 public _maxLiquidityFee = 5;
uint256 public _maxLiquidityFee = 4;
uint256 public _liquidityFee = 4;
uint256 public _liquidityFee = 2;
uint256 private _previousLiquidityFee = _liquidityFee;
uint256 private _previousLiquidityFee = _liquidityFee;


IPancakeRouter02 public immutable pancakeRouter;
IPancakeRouter02 public immutable pancakeRouter;
address public immutable pancakePair;
address public immutable pancakePair;

bool inSwapAndLiquify;
bool inSwapAndLiquify;
bool public swapAndLiquifyEnabled = true;
bool public swapAndLiquifyEnabled = true;

uint256 public _maxTxAmount = 5 * 10**6 * 10**6 * 10**9;
uint256 public _maxTxAmount = 5 * 10**6 * 10**6 * 10**9;
uint256 private constant numTokensSellToAddToLiquidity = 5 * 10**5 * 10**6 * 10**9;
uint256 private constant numTokensSellToAddToLiquidity = 5 * 10**5 * 10**6 * 10**9;

event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
event SwapAndLiquifyEnabledUpdated(bool enabled);
event SwapAndLiquifyEnabledUpdated(bool enabled);
event SwapAndLiquify(
event SwapAndLiquify(
uint256 tokensSwapped,
uint256 tokensSwapped,
uint256 ethReceived,
uint256 ethReceived,
uint256 tokensIntoLiquidity
uint256 tokensIntoLiquidity
);
);

modifier lockTheSwap {
modifier lockTheSwap {
inSwapAndLiquify = true;
inSwapAndLiquify = true;
_;
_;
inSwapAndLiquify = false;
inSwapAndLiquify = false;
}
}

constructor () {
constructor () {
_rOwned[_msgSender()] = _rTotal;
_rOwned[_msgSender()] = _rTotal;

IPancakeRouter02 _pancakeRouter = IPancakeRouter02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
IPancakeRouter02 _pancakeRouter = IPancakeRouter02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
// Create a uniswap pair for this new token
// Create a uniswap pair for this new token
pancakePair = IPancakeFactory(_pancakeRouter.factory())
pancakePair = IPancakeFactory(_pancakeRouter.factory())
.createPair(address(this), _pancakeRouter.WETH());
.createPair(address(this), _pancakeRouter.WETH());


// set the rest of the contract variables
// set the rest of the contract variables
pancakeRouter = _pancakeRouter;
pancakeRouter = _pancakeRouter;

//exclude owner and this contract from fee and charity multisig
//exclude owner and this contract from fee and charity multisig
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[CHARITY_MULTISIG] = true;
_isExcludedFromFee[CHARITY_DAO] = true;



emit Transfer(address(0), _msgSender(), _tTotal);
emit Transfer(address(0), _msgSender(), _tTotal);
}
}


function name() public pure returns (string memory) {
function name() public pure returns (string memory) {
return _name;
return _name;
}
}


function symbol() public pure returns (string memory) {
function symbol() public pure returns (string memory) {
return _symbol;
return _symbol;
}
}


function decimals() public pure returns (uint8) {
function decimals() public pure returns (uint8) {
return _decimals;
return _decimals;
}
}


function totalSupply() public pure override returns (uint256) {
function totalSupply() public pure override returns (uint256) {
return _tTotal;
return _tTotal;
}
}


function balanceOf(address account) public view override returns (uint256) {
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
return tokenFromReflection(_rOwned[account]);
}
}


function transfer(address recipient, uint256 amount) public override returns (bool) {
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
_transfer(_msgSender(), recipient, amount);
return true;
return true;
}
}


function allowance(address owner, address spender) public view override returns (uint256) {
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
return _allowances[owner][spender];
}
}


function approve(address spender, uint256 amount) public override returns (bool) {
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
_approve(_msgSender(), spender, amount);
return true;
return true;
}
}


function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
return true;
}
}


function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
return true;
}
}


function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
return true;
}
}


function isExcludedFromReward(address account) public view returns (bool) {
function isExcludedFromReward(address account) public view returns (bool) {
return _isExcluded[account];
return _isExcluded[account];
}
}


function totalFees() public view returns (uint256) {
function totalFees() public view returns (uint256) {
return _tFeeTotal;
return _tFeeTotal;
}
}


function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) {
function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) {
require(tAmount <= _tTotal, "Amount must be less than supply");
require(tAmount <= _tTotal, "Amount must be less than supply");
if (!deductTransferFee) {
if (!deductTransferFee) {
(uint256 rAmount,,,,,,) = _getValues(tAmount);
(uint256 rAmount,,,,,,) = _getValues(tAmount);
return rAmount;
return rAmount;
} else {
} else {
(,uint256 rTransferAmount,,,,,) = _getValues(tAmount);
(,uint256 rTransferAmount,,,,,) = _getValues(tAmount);
return rTransferAmount;
return rTransferAmount;
}
}
}
}


function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate();
uint256 currentRate = _getRate();
return rAmount.div(currentRate);
return rAmount.div(currentRate);
}
}


function excludeFromReward(address account) public onlyOwner() {
function excludeFromReward(address account) public onlyOwner() {
// require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude Uniswap router.');
// require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude Uniswap router.');
require(!_isExcluded[account], "Account is already excluded");
require(!_isExcluded[account], "Account is already excluded");
if(_rOwned[account] > 0) {
if(_rOwned[account] > 0) {
_tOwned[account] = tokenFromReflection(_rOwned[account]);
_tOwned[account] = tokenFromReflection(_rOwned[account]);
}
}
_isExcluded[account] = true;
_isExcluded[account] = true;
_excluded.push(account);
_excluded.push(account);
}
}


function includeInReward(address account) external onlyOwner() {
function includeInReward(address account) external onlyOwner() {
require(_isExcluded[account], "Account is not excluded");
require(_isExcluded[account], "Account is not excluded");
for (uint256 i = 0; i < _excluded.length; i++) {
for (uint256 i = 0; i < _excluded.length; i++) {
if (_excluded[i] == account) {
if (_excluded[i] == account) {
_excluded[i] = _excluded[_excluded.length - 1];
_excluded[i] = _excluded[_excluded.length - 1];
_tOwned[account] = 0;
_tOwned[account] = 0;
_isExcluded[account] = false;
_isExcluded[account] = false;
_excluded.pop();
_excluded.pop();
break;
break;
}
}
}
}
}
}

function excludeFromFee(address account) public onlyOwner {
function excludeFromFee(address account) public onlyOwner {
_isExcludedFromFee[account] = true;
_isExcludedFromFee[account] = true;
}
}

function includeInFee(address account) public onlyOwner {
function includeInFee(address account) public onlyOwner {
_isExcludedFromFee[account] = false;
_isExcludedFromFee[account] = false;
}
}


function setCharityFeePercent(uint256 fee) external onlyOwner() {
function setCharityFeePercent(uint256 fee) external onlyOwner() {
require(fee <= _maxCharityFee, 'Tax exceeds maximum');
require(fee <= _maxCharityFee, 'Tax exceeds maximum');
_charityFee = fee;
_charityFee = fee;
}
}

function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
require(taxFee <= _maxTaxFee, 'Tax exceeds maximum');
require(taxFee <= _maxTaxFee, 'Tax exceeds maximum');
_taxFee = taxFee;
_taxFee = taxFee;
}
}

function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
require(liquidityFee <= _maxLiquidityFee, 'Tax exceeds maximum');
require(liquidityFee <= _maxLiquidityFee, 'Tax exceeds maximum');
_liquidityFee = liquidityFee;
_liquidityFee = liquidityFee;
}
}

function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() {
function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() {
_maxTxAmount = _tTotal.mul(maxTxPercent).div(
_maxTxAmount = _tTotal.mul(maxTxPercent).div(
10**2
10**2
);
);
}
}


function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
swapAndLiquifyEnabled = _enabled;
swapAndLiquifyEnabled = _enabled;
emit SwapAndLiquifyEnabledUpdated(_enabled);
emit SwapAndLiquifyEnabledUpdated(_enabled);
}
}

//to receive ETH from pancakeRouter when swapping
//to receive ETH from pancakeRouter when swapping
receive() external payable {}
receive() external payable {}


function _reflectFee(uint256 rFee, uint256 tFee) private {
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
}


// Checked
// Checked
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256) {
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256) {
(uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
(uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount,, uint256 rFee,) = _getRValues(tAmount, tCharity, tFee, tLiquidity, _getRate());
(uint256 rAmount, uint256 rTransferAmount,, uint256 rFee,) = _getRValues(tAmount, tCharity, tFee, tLiquidity, _getRate());
return (rAmount, rTransferAmount, rFee, tTransferAmount, tCharity, tFee, tLiquidity);
return (rAmount, rTransferAmount, rFee, tTransferAmount, tCharity, tFee, tLiquidity);
}
}




// Checked
// Checked
function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256) {
function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256) {
uint256 tCharity = calculateCharityFee(tAmount);
uint256 tCharity = calculateCharityFee(tAmount);
uint256 tFee = calculateTaxFee(tAmount);
uint256 tFee = calculateTaxFee(tAmount);
uint256 tLiquidity = calculateLiquidityFee(tAmount);
uint256 tLiquidity = calculateLiquidityFee(tAmount);
uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity).sub(tCharity);
uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity).sub(tCharity);
return (tTransferAmount, tCharity, tFee, tLiquidity);
return (tTransferAmount, tCharity, tFee, tLiquidity);
}
}


// Checked
// Checked
function _getRValues(uint256 tAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256,uint256,uint256) {
function _getRValues(uint256 tAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256,uint256,uint256) {
uint256 rAmount = tAmount.mul(currentRate);
uint256 rAmount = tAmount.mul(currentRate);
uint256 rFee = tFee.mul(currentRate);
uint256 rFee = tFee.mul(currentRate);
uint256 rLiquidity = tLiquidity.mul(currentRate);
uint256 rLiquidity = tLiquidity.mul(currentRate);
uint256 rCharity = tCharity.mul(currentRate);
uint256 rCharity = tCharity.mul(currentRate);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity).sub(rCharity);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity).sub(rCharity);
return (rAmount, rTransferAmount, rCharity, rFee, rLiquidity);
return (rAmount, rTransferAmount, rCharity, rFee, rLiquidity);
}
}


function _getRate() private view returns(uint256) {
function _getRate() private view returns(uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply.div(tSupply);
return rSupply.div(tSupply);
}
}


function _getCurrentSupply() private view returns(uint256, uint256) {
function _getCurrentSupply() private view returns(uint256, uint256) {
uint256 rSupply = _rTotal;
uint256 rSupply = _rTotal;
uint256 tSupply = _tTotal;
uint256 tSupply = _tTotal;
for (uint256 i = 0; i < _excluded.length; i++) {
for (uint256 i = 0; i < _excluded.length; i++) {
if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
rSupply = rSupply.sub(_rOwned[_excluded[i]]);
rSupply = rSupply.sub(_rOwned[_excluded[i]]);
tSupply = tSupply.sub(_tOwned[_excluded[i]]);
tSupply = tSupply.sub(_tOwned[_excluded[i]]);
}
}
if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
return (rSupply, tSupply);
return (rSupply, tSupply);
}
}


function _takeCharity(uint256 tCharity) private {
function _takeCharity(uint256 tCharity) private {
uint256 currentRate = _getRate();
uint256 currentRate = _getRate();
uint256 rCharity = tCharity.mul(currentRate);
uint256 rCharity = tCharity.mul(currentRate);
_rOwned[CHARITY_MULTISIG] = _rOwned[CHARITY_MULTISIG].add(rCharity);
_rOwned[CHARITY_DAO] = _rOwned[CHARITY_DAO].add(rCharity);
if(_isExcluded[CHARITY_MULTISIG])
if(_isExcluded[CHARITY_DAO])
_tOwned[CHARITY_MULTISIG] = _tOwned[CHARITY_MULTISIG].add(tCharity);
_tOwned[CHARITY_DAO] = _tOwned[CHARITY_DAO].add(tCharity);
}
}

function _takeLiquidity(uint256 tLiquidity) private {
function _takeLiquidity(uint256 tLiquidity) private {
uint256 currentRate = _getRate();
uint256 currentRate = _getRate();
uint256 rLiquidity = tLiquidity.mul(currentRate);
uint256 rLiquidity = tLiquidity.mul(currentRate);
_rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
_rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
if(_isExcluded[address(this)])
if(_isExcluded[address(this)])
_tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
_tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
}
}

function calculateCharityFee(uint256 _amount) private view returns (uint256) {
function calculateCharityFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_charityFee).div(
return _amount.mul(_charityFee).div(
10**2
10**2
);
);
}
}


function calculateTaxFee(uint256 _amount) private view returns (uint256) {
function calculateTaxFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_taxFee).div(
return _amount.mul(_taxFee).div(
10**2
10**2
);
);
}
}


function calculateLiquidityFee(uint256 _amount) private view returns (uint256) {
function calculateLiquidityFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_liquidityFee).div(
return _amount.mul(_liquidityFee).div(
10**2
10**2
);
);
}
}

function removeAllFee() private {
function removeAllFee() private {
if(_taxFee == 0 && _liquidityFee == 0 && _charityFee == 0) return;
if(_taxFee == 0 && _liquidityFee == 0 && _charityFee == 0) return;

_previousCharityFee = _charityFee;
_previousCharityFee = _charityFee;
_previousTaxFee = _taxFee;
_previousTaxFee = _taxFee;
_previousLiquidityFee = _liquidityFee;
_previousLiquidityFee = _liquidityFee;

_charityFee = 0;
_charityFee = 0;
_taxFee = 0;
_taxFee = 0;
_liquidityFee = 0;
_liquidityFee = 0;
}
}

function restoreAllFee() private {
function restoreAllFee() private {
_charityFee = _previousCharityFee;
_charityFee = _previousCharityFee;
_taxFee = _previousTaxFee;
_taxFee = _previousTaxFee;
_liquidityFee = _previousLiquidityFee;
_liquidityFee = _previousLiquidityFee;
}
}

function isExcludedFromFee(address account) public view returns(bool) {
function isExcludedFromFee(address account) public view returns(bool) {
return _isExcludedFromFee[account];
return _isExcludedFromFee[account];
}
}


function _approve(address owner, address spender, uint256 amount) private {
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
require(spender != address(0), "ERC20: approve to the zero address");


_allowances[owner][spender] = amount;
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
emit Approval(owner, spender, amount);
}
}


function _transfer(
function _transfer(
address from,
address from,
address to,
address to,
uint256 amount
uint256 amount
) private {
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
require(amount > 0, "Transfer amount must be greater than zero");
if(from != owner() && to != owner())
if(from != owner() && to != owner())
require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");


// is the token balance of this contract address over the min number of
// is the token balance of this contract address over the min number of
// tokens that we need to initiate a swap + liquidity lock?
// tokens that we need to initiate a swap + liquidity lock?
// also, don't get caught in a circular liquidity event.
// also, don't get caught in a circular liquidity event.
// also, don't swap & liquify if sender is uniswap pair.
// also, don't swap & liquify if sender is uniswap pair.
uint256 contractTokenBalance = balanceOf(address(this));
uint256 contractTokenBalance = balanceOf(address(this));

if(contractTokenBalance >= _maxTxAmount)
if(contractTokenBalance >= _maxTxAmount)
{
{
contractTokenBalance = _maxTxAmount;
contractTokenBalance = _maxTxAmount;
}
}

bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;
bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;
if (
if (
overMinTokenBalance &&
overMinTokenBalance &&
!inSwapAndLiquify &&
!inSwapAndLiquify &&
from != pancakePair &&
from != pancakePair &&
swapAndLiquifyEnabled
swapAndLiquifyEnabled
) {
) {
contractTokenBalance = numTokensSellToAddToLiquidity;
contractTokenBalance = numTokensSellToAddToLiquidity;
//add liquidity
//add liquidity
swapAndLiquify(contractTokenBalance);
swapAndLiquify(contractTokenBalance);
}
}

//indicates if fee should be deducted from transfer
//indicates if fee should be deducted from transfer
bool takeFee = true;
bool takeFee = true;

//if any account belongs to _isExcludedFromFee account then remove the fee
//if any account belongs to _isExcludedFromFee account then remove the fee
if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
takeFee = false;
takeFee = false;
}
}

//transfer amount, it will take tax, burn, liquidity fee
//transfer amount, it will take tax, burn, liquidity fee
_tokenTransfer(from,to,amount,takeFee);
_tokenTransfer(from,to,amount,takeFee);
}
}


// This is to rescue anything other than BNB or Token sent into the contract
// This is to rescue anything other than BNB or Token sent into the contract
function adminRescueTokens(address token, uint256 amount) external onlyOwner() {
function adminRescueTokens(address token, uint256 amount) external onlyOwner() {
require(token != address(this) && token != address(pancakeRouter.WETH()), 'Cannot withdraw primary tokens');
require(token != address(this) && token != address(pancakeRouter.WETH()), 'Cannot withdraw primary tokens');
IERC20(token).transfer(msg.sender, amount);
IERC20(token).transfer(msg.sender, amount);
}
}


// This allows us to take any TAMA owned by the contract and zap it into liquidity
// This allows us to take any SHIBBY owned by the contract and zap it into liquidity
function swapBalanceToLiquidity(uint256 amount) external onlyOwner() {
function swapBalanceToLiquidity(uint256 amount) external onlyOwner() {
require(amount <= balanceOf(address(this)), 'Not enough tokens for swap');
require(amount <= balanceOf(address(this)), 'Not enough tokens for swap');


// split the contract balance into halves
// split the contract balance into halves
uint256 half = amount.div(2);
uint256 half = amount.div(2);
uint256 otherHalf = amount.sub(half);
uint256 otherHalf = amount.sub(half);


// capture the contract's current BNB balance.
// capture the contract's current BNB balance.
// this is so that we can capture exactly the amount of BNB that the
// this is so that we can capture exactly the amount of BNB that the
// swap creates, and not make the liquidity event include any BNB that
// swap creates, and not make the liquidity event include any BNB that
// has been manually sent to the contract
// has been manually sent to the contract
// Leftover BNB can always be swapped to token in another external method
// Leftover BNB can always be swapped to token in another external method
uint256 initialBalance = address(this).balance;
uint256 initialBalance = address(this).balance;


// swap tokens for ETH
// swap tokens for ETH
swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered


// how much ETH did we just swap into?
// how much ETH did we just swap into?
uint256 newBalance = address(this).balance.sub(initialBalance);
uint256 newBalance = address(this).balance.sub(initialBalance);


// add liquidity to pancake
// add liquidity to pancake
addLiquidity(otherHalf, newBalance);
addLiquidity(otherHalf, newBalance);

emit SwapAndLiquify(half, newBalance, otherHalf);
emit SwapAndLiquify(half, newBalance, otherHalf);
}
}


function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
// split the contract balance into halves
// split the contract balance into halves
uint256 half = contractTokenBalance.div(2);
uint256 half = contractTokenBalance.div(2);
uint256 otherHalf = contractTokenBalance.sub(half);
uint256 otherHalf = contractTokenBalance.sub(half);


// capture the contract's current ETH balance.
// capture the contract's current ETH balance.
// this is so that we can capture exactly the amount of ETH that the
// this is so that we can capture exactly the amount of ETH that the
// swap creates, and not make the liquidity event include any ETH that
// swap creates, and not make the liquidity event include any ETH that
// has been manually sent to the contract
// has been manually sent to the contract
uint256 initialBalance = address(this).balance;
uint256 initialBalance = address(this).balance;


// swap tokens for ETH
// swap tokens for ETH
swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered


// how much ETH did we just swap into?
// how much ETH did we just swap into?
uint256 newBalance = address(this).balance.sub(initialBalance);
uint256 newBalance = address(this).balance.sub(initialBalance);


// add liquidity to pancake
// add liquidity to pancake
addLiquidity(otherHalf, newBalance);
addLiquidity(otherHalf, newBalance);

emit SwapAndLiquify(half, newBalance, otherHalf);
emit SwapAndLiquify(half, newBalance, otherHalf);
}
}


// adminRescueTokens cannot rescue wBNB, so any wBNB sent to the contract can only be used to deflate supply
// adminRescueTokens cannot rescue wBNB, so any wBNB sent to the contract can only be used to deflate supply
// Deflationary pressure because purchased tokens are sent to BURN_ADDRESS
// Deflationary pressure because purchased tokens are sent to BURN_ADDRESS
function swapWBNBForTokensAndBurn(uint256 amountBNB, uint256 minTokenAmountOut) external onlyOwner() {
function swapWBNBForTokensAndBurn(uint256 amountBNB, uint256 minTokenAmountOut) external onlyOwner() {
address[] memory path = new address[](2);
address[] memory path = new address[](2);
path[0] = pancakeRouter.WETH();
path[0] = pancakeRouter.WETH();
path[1] = address(this);
path[1] = address(this);


// make the swap
// make the swap
pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountBNB,
amountBNB,
minTokenAmountOut,
minTokenAmountOut,
path,
path,
BURN_ADDRESS,
BURN_ADDRESS,
block.timestamp
block.timestamp
);
);
}
}


// Added to address CERTIK SSL-03
// Added to address CERTIK SSL-03
function swapBNBForTokensAndBurn(uint256 amountBNB, uint256 minTokenAmountOut) external onlyOwner() {
function swapBNBForTokensAndBurn(uint256 amountBNB, uint256 minTokenAmountOut) external onlyOwner() {
address[] memory path = new address[](2);
address[] memory path = new address[](2);
path[0] = pancakeRouter.WETH();
path[0] = pancakeRouter.WETH();
path[1] = address(this);
path[1] = address(this);


// make the swap
// make the swap
pancakeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: amountBNB}(
pancakeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: amountBNB}(
minTokenAmountOut,
minTokenAmountOut,
path,
path,
BURN_ADDRESS,
BURN_ADDRESS,
block.timestamp
block.timestamp
);
);
}
}


function swapTokensForEth(uint256 tokenAmount) private {
function swapTokensForEth(uint256 tokenAmount) private {
address[] memory path = new address[](2);
address[] memory path = new address[](2);
path[0] = address(this);
path[0] = address(this);
path[1] = pancakeRouter.WETH();
path[1] = pancakeRouter.WETH();


_approve(address(this), address(pancakeRouter), tokenAmount);
_approve(address(this), address(pancakeRouter), tokenAmount);


// make the swap
// make the swap
pancakeRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
pancakeRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
tokenAmount,
0, // accept any amount of ETH
0, // accept any amount of ETH
path,
path,
address(this),
address(this),
block.timestamp
block.timestamp
);
);
}
}


function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
// approve token transfer to cover all possible scenarios
// approve token transfer to cover all possible scenarios
_approve(address(this), address(pancakeRouter), tokenAmount);
_approve(address(this), address(pancakeRouter), tokenAmount);


// add the liquidity
// add the liquidity
pancakeRouter.addLiquidityETH{value: ethAmount}(
pancakeRouter.addLiquidityETH{value: ethAmount}(
address(this),
address(this),
tokenAmount,
tokenAmount,
0, // slippage is unavoidable
0, // slippage is unavoidable
0, // slippage is unavoidable
0, // slippage is unavoidable
BURN_ADDRESS, // burn the LP
BURN_ADDRESS, // burn the LP
block.timestamp
block.timestamp
);
);
}
}


//this method is responsible for taking all fee, if takeFee is true
//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
if(!takeFee)
if(!takeFee)
removeAllFee();
removeAllFee();

if (_isExcluded[sender] && !_isExcluded[recipient]) {
if (_isExcluded[sender] && !_isExcluded[recipient]) {
_transferFromExcluded(sender, recipient, amount);
_transferFromExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
_transferToExcluded(sender, recipient, amount);
_transferToExcluded(sender, recipient, amount);
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
_transferBothExcluded(sender, recipient, amount);
_transferBothExcluded(sender, recipient, amount);
} else {
} else {
_transferStandard(sender, recipient, amount);
_transferStandard(sender, recipient, amount);
}
}

if(!takeFee)
if(!takeFee)
restoreAllFee();
restoreAllFee();
}
}


function _transferStandard(address sender, address recipient, uint256 tAmount) private {
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeCharity(tCharity);
_takeCharity(tCharity);
_takeLiquidity(tLiquidity);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
}


function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeCharity(tCharity);
_takeCharity(tCharity);
_takeLiquidity(tLiquidity);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
}


function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeCharity(tCharity);
_takeCharity(tCharity);
_takeLiquidity(tLiquidity);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
}


function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tCharity, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);


_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTrans
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeCharity(tCharity);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}

}