Deploy and add liquidity to a new token (safemoon fork)?

I need some help to deploy and add initial liquidity to a new token.
I have a contract similar to safemoon and bafe and I failed 2 times already :slight_smile:

:computer: Environment

:memo:Details

:1234: Code to reproduce

1 Like

Hi iulianh, welcome to the forums.

If you are new, you should start by following the tutorial over at OpenZeppelin Upgrades: Step by Step Tutorial for Hardhat

If you've follow that and have properly set up your dev environment then follow along my mini guide over here on how you can provide liquidity.

After following these tutorials, if you still have issues please link your contracts.

Thank you.

We get error Transfer_failed (pancakeswap) after a few swaps.

I don’t know how to fix this.

Hi Tsushima - could you contact with me through private message, I have some questions and I think I will have job for you

Hi, please help. I deployed the contract 0xb43cff3901efa40f1647c356940c34683c8f3aa3 but its impossible to get verified on BSCscan
here is my code:

pragma solidity ^0.8.1;

// SPDX-License-Identifier: WTFPL
import “@openzeppelin/contracts/access/Ownable.sol”;
import “@openzeppelin/contracts/token/ERC20/IERC20.sol”;
import “@openzeppelin/contracts/utils/math/SafeMath.sol”;
import “@openzeppelin/contracts/utils/Address.sol”;

interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}

interface IUniswapV2Router02 {
function factory() 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);

function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external;

function removeLiquidity(
    address tokenA,
    address tokenB,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB);

}

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

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

mapping (address => bool) private _isExcludedFromFee;

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

uint256 private constant MAX = ~uint256(0);
uint256 private _tTotal = 1000000000 * 10**6 * 10**9;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _tFeeTotal;

string private _name = "Akoin";
string private _symbol = "AKOIN";
uint8 private _decimals = 9;

uint256 public _taxFee = 2; // redistribution: 2%
uint256 private _previousTaxFee = _taxFee;

uint256 public _liquidityFee = 2; // liquidity fee: 2%, 2% of this fee goes to the burnPercentage
uint256 private _previousLiquidityFee = _liquidityFee;

// << Custom feature: Burning >>
// Each transaction a 2% fee is deducted as well which is not reflected (distributed), 
// but instead it is simply burned. The mechanism for this is similar to the liquidityFee
// The tokens are simply send to this contract and are only burned once numTokensSellToAddToLiquidity
// is reached.
uint256 public _burnFee = 2; // percentage of liquidityFee that is burned
uint256 private _previousBurnFee = _burnFee;

IUniswapV2Router02 public immutable uniswapV2Router;
address public immutable uniswapV2Pair;

address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;

bool inSwapAndLiquify;
bool public swapAndLiquifyEnabled = true;

uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9;
uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9;

// << Custom feature: Liquidity burning >>
// To become even more rug proof, all liquidity tokens are send to this contract.
// Once every month, the owner can decide to do a liquidity burn.
// The maxLiquidityBurnPercentag will then be removed from liquidity. The
// resulting bnb is swapped to Akoin. Finally all this Akoin is burned.
uint256 public constant maxLiquidityBurnPercentage = 5;
uint256 public constant minLiquidityBurnInterval = 864000;
uint256 public lastLiquidityBurn = 0;

event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
event SwapAndLiquifyEnabledUpdated(bool enabled);
event SwapAndLiquify(
    uint256 tokensSwapped,
    uint256 ethReceived,
    uint256 tokensIntoLiqudity
);
event RemoveLiquidityAndBurn(
    uint256 tokensBurned
);

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

IERC20 wbnb = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);

constructor () {
    _rOwned[_msgSender()] = _rTotal;
    // Pancakeswap V2
    IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
     // Create a uniswap pair for this new token (AKOIN/WBNB)
    uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
        .createPair(address(this), address(wbnb));

    // set the rest of the contract variables
    uniswapV2Router = _uniswapV2Router;
    
    //exclude owner and this contract from fee
    _isExcludedFromFee[owner()] = true;
    _isExcludedFromFee[address(this)] = true;
    _isExcluded[BURN_ADDRESS] = true;
    
    emit Transfer(address(0), _msgSender(), _tTotal);
}

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

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

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

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

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

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

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

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

function transferFrom(address sender, address recipient, uint256 amount) public 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 isExcludedFromReward(address account) public view returns (bool) {
    return _isExcluded[account];
}

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

function deliver(uint256 tAmount) public {
    address sender = _msgSender();
    require(!_isExcluded[sender], "Excluded addresses cannot call this function");
    (uint256 rAmount,,,,,) = _getValues(tAmount);
    _rOwned[sender] = _rOwned[sender].sub(rAmount);
    _rTotal = _rTotal.sub(rAmount);
    _tFeeTotal = _tFeeTotal.add(tAmount);
}

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

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

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

// removes amount lpTokens from the contract, exchanging them for WBNB and AKOIN
// The WBNB is exchanged for Akoin and finally all generated Akoin is burned.
function removeLiquidityAndBurn(uint256 amount) public onlyOwner() {
    require(lastLiquidityBurn.add(minLiquidityBurnInterval) < block.number, "Too Soon");
    lastLiquidityBurn = lastLiquidityBurn.add(minLiquidityBurnInterval);

    uint256 balance = IERC20(uniswapV2Pair).balanceOf(address(this));
    require(amount > 0 && amount < balance.mul(maxLiquidityBurnPercentage).div(10**2));

    uint256 prevAkoinBal = balanceOf(address(this));

    uniswapV2Router.removeLiquidity(
        address(this),
        address(wbnb),
        amount,
        0,
        0,
        address(this),
        block.timestamp
    );

    uint256 wbnbBalance = wbnb.balanceOf(address(this));
    if (wbnbBalance > 0) {
        address[] memory path = new address[](2);
        path[0] = address(wbnb);
        path[1] = address(this);
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            wbnbBalance,
            0,
            path,
            address(this),
            block.timestamp
        );
    }
    uint256 AkoinBal = balanceOf(address(this));
    uint256 toBurn = AkoinBal.sub(prevAkoinBal);
    require(toBurn > 0, "Nothing to burn");

    _burnFrom(address(this), toBurn);
    emit RemoveLiquidityAndBurn(toBurn);
}

function includeInReward(address account) external onlyOwner() {
    require(_isExcluded[account], "Account is already excluded");
    for (uint256 i = 0; i < _excluded.length; i++) {
        if (_excluded[i] == account) {
            _excluded[i] = _excluded[_excluded.length - 1];
            _tOwned[account] = 0;
            _isExcluded[account] = false;
            _excluded.pop();
            break;
        }
    }
}
    function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
    (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
    _tOwned[sender] = _tOwned[sender].sub(tAmount);
    _rOwned[sender] = _rOwned[sender].sub(rAmount);
    _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
    _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);        
    _takeLiquidity(tLiquidity);
    _reflectFee(rFee, tFee);
    emit Transfer(sender, recipient, tTransferAmount);
}

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

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

function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
    _taxFee = taxFee;
}

function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
    _liquidityFee = liquidityFee;
}

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

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

 //to recieve ETH from uniswapV2Router when swaping
receive() external payable {}

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

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

function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
    uint256 tFee = calculateTaxFee(tAmount);
    uint256 tLiquidityAndBurn = calculateLiquidityAndBurnFee(tAmount);
    uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidityAndBurn);
    return (tTransferAmount, tFee, tLiquidityAndBurn);
}

function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidityAndBurn, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
    uint256 rAmount = tAmount.mul(currentRate);
    uint256 rFee = tFee.mul(currentRate);
    uint256 rLiquidityAndBurn = tLiquidityAndBurn.mul(currentRate);
    uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidityAndBurn);
    return (rAmount, rTransferAmount, rFee);
}

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

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

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

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

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

function removeAllFee() private {
    if(_taxFee == 0 && _liquidityFee == 0) return;
    
    _previousTaxFee = _taxFee;
    _previousLiquidityFee = _liquidityFee;
    
    _taxFee = 0;
    _liquidityFee = 0;
}

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

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

function _approve(address owner, address spender, uint256 amount) private {
    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 _transfer(
    address from,
    address to,
    uint256 amount
) private {
    require(from != address(0), "ERC20: transfer from the zero address");
    require(to != address(0), "ERC20: transfer to the zero address");
    require(amount > 0, "Transfer amount must be greater than zero");
    if(from != owner() && to != owner())
        require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
    
    if(to == BURN_ADDRESS) {
        _burnFrom(from, amount);
        return;
    }

    // is the token balance of this contract address over the min number of
    // tokens that we need to initiate a swap + liquidity lock?
    // also, don't get caught in a circular liquidity event.
    // also, don't swap & liquify if sender is uniswap pair.
    uint256 contractTokenBalance = balanceOf(address(this));
    
    if(contractTokenBalance >= _maxTxAmount)
    {
        contractTokenBalance = _maxTxAmount;
    }
    
    bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;
    if (
        overMinTokenBalance &&
        !inSwapAndLiquify &&
        from != uniswapV2Pair
    ) {
        contractTokenBalance = numTokensSellToAddToLiquidity;
        //add liquidity
        swapAndLiquify(contractTokenBalance);
    }
    
    //indicates if fee should be deducted from transfer
    bool takeFee = true;
    
    //if any account belongs to _isExcludedFromFee account then remove the fee
    if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
        takeFee = false;
    }
    
    //transfer amount, it will take tax, burn, liquidity fee
    _tokenTransfer(from,to,amount,takeFee);
}
function _burnFrom(address sender, uint256 rAmount) private {
    uint256 rAccountBalance = _rOwned[sender];
    uint256 tAccountBalance = _tOwned[sender];
    uint256 tAmount = tAccountBalance.mul(rAmount).div(rAccountBalance);
    require(rAccountBalance >= rAmount, "ERC20: burn amount exceeds balance");
    _rOwned[sender] = rAccountBalance.sub(rAmount);
    _tOwned[sender] = tAccountBalance.sub(tAmount);
    _tTotal = _tTotal.sub(tAmount); // Take tokens out of circulation
    _rTotal = _rTotal.sub(rAmount);
    
    emit Transfer(sender, BURN_ADDRESS, rAmount);
}

function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
    // burn burnFee
    if (_burnFee > 0){
        uint256 burnFee = contractTokenBalance.mul(_burnFee).div(_burnFee.add(_liquidityFee));
        contractTokenBalance = contractTokenBalance.sub(burnFee);
        _burnFrom(address(this), burnFee);
    }
    if(!swapAndLiquifyEnabled){
        return;
    }
    // split the contract balance into halves
    uint256 half = contractTokenBalance.div(2);
    uint256 otherHalf = contractTokenBalance.sub(half);

    // capture the contract's current ETH balance.
    // 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
    // has been manually sent to the contract
    uint256 initialBalance = address(this).balance;

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

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

    // add liquidity to uniswap
    addLiquidity(otherHalf, newBalance);
    
    emit SwapAndLiquify(half, newBalance, otherHalf);
}

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] = address(wbnb);

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

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

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

    // add the liquidity
    uniswapV2Router.addLiquidity(
        address(this),
        address(wbnb),
        tokenAmount,
        ethAmount,
        0, // slippage is unavoidable
        0, // slippage is unavoidable
        address(this),
        block.timestamp
    );
}

//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
    if(!takeFee)
        removeAllFee();
    
    if (_isExcluded[sender] && !_isExcluded[recipient]) {
        _transferFromExcluded(sender, recipient, amount);
    } else if (!_isExcluded[sender] && _isExcluded[recipient]) {
        _transferToExcluded(sender, recipient, amount);
    } else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
        _transferStandard(sender, recipient, amount);
    } else if (_isExcluded[sender] && _isExcluded[recipient]) {
        _transferBothExcluded(sender, recipient, amount);
    } else {
        _transferStandard(sender, recipient, amount);
    }
    
    if(!takeFee)
        restoreAllFee();
}

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

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

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

}
pragma solidity ^0.8.1;

// SPDX-License-Identifier: WTFPL
import “@openzeppelin/contracts/access/Ownable.sol”;
import “@openzeppelin/contracts/token/ERC20/IERC20.sol”;
import “@openzeppelin/contracts/utils/math/SafeMath.sol”;
import “@openzeppelin/contracts/utils/Address.sol”;

interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}

interface IUniswapV2Router02 {
function factory() 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);

function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external;

function removeLiquidity(
    address tokenA,
    address tokenB,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB);

}

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

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

mapping (address => bool) private _isExcludedFromFee;

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

uint256 private constant MAX = ~uint256(0);
uint256 private _tTotal = 1000000000 * 10**6 * 10**9;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _tFeeTotal;

string private _name = "Akoin";
string private _symbol = "AKOIN";
uint8 private _decimals = 9;

uint256 public _taxFee = 2; // redistribution: 2%
uint256 private _previousTaxFee = _taxFee;

uint256 public _liquidityFee = 2; // liquidity fee: 2%, 2% of this fee goes to the burnPercentage
uint256 private _previousLiquidityFee = _liquidityFee;

// << Custom feature: Burning >>
// Each transaction a 2% fee is deducted as well which is not reflected (distributed), 
// but instead it is simply burned. The mechanism for this is similar to the liquidityFee
// The tokens are simply send to this contract and are only burned once numTokensSellToAddToLiquidity
// is reached.
uint256 public _burnFee = 2; // percentage of liquidityFee that is burned
uint256 private _previousBurnFee = _burnFee;

IUniswapV2Router02 public immutable uniswapV2Router;
address public immutable uniswapV2Pair;

address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;

bool inSwapAndLiquify;
bool public swapAndLiquifyEnabled = true;

uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9;
uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9;

// << Custom feature: Liquidity burning >>
// To become even more rug proof, all liquidity tokens are send to this contract.
// Once every month, the owner can decide to do a liquidity burn.
// The maxLiquidityBurnPercentag will then be removed from liquidity. The
// resulting bnb is swapped to Akoin. Finally all this Akoin is burned.
uint256 public constant maxLiquidityBurnPercentage = 5;
uint256 public constant minLiquidityBurnInterval = 864000;
uint256 public lastLiquidityBurn = 0;

event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
event SwapAndLiquifyEnabledUpdated(bool enabled);
event SwapAndLiquify(
    uint256 tokensSwapped,
    uint256 ethReceived,
    uint256 tokensIntoLiqudity
);
event RemoveLiquidityAndBurn(
    uint256 tokensBurned
);

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

IERC20 wbnb = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);

constructor () {
    _rOwned[_msgSender()] = _rTotal;
    // Pancakeswap V2
    IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
     // Create a uniswap pair for this new token (AKOIN/WBNB)
    uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
        .createPair(address(this), address(wbnb));

    // set the rest of the contract variables
    uniswapV2Router = _uniswapV2Router;
    
    //exclude owner and this contract from fee
    _isExcludedFromFee[owner()] = true;
    _isExcludedFromFee[address(this)] = true;
    _isExcluded[BURN_ADDRESS] = true;
    
    emit Transfer(address(0), _msgSender(), _tTotal);
}

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

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

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

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

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

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

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

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

function transferFrom(address sender, address recipient, uint256 amount) public 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 isExcludedFromReward(address account) public view returns (bool) {
    return _isExcluded[account];
}

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

function deliver(uint256 tAmount) public {
    address sender = _msgSender();
    require(!_isExcluded[sender], "Excluded addresses cannot call this function");
    (uint256 rAmount,,,,,) = _getValues(tAmount);
    _rOwned[sender] = _rOwned[sender].sub(rAmount);
    _rTotal = _rTotal.sub(rAmount);
    _tFeeTotal = _tFeeTotal.add(tAmount);
}

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

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

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

// removes amount lpTokens from the contract, exchanging them for WBNB and AKOIN
// The WBNB is exchanged for Akoin and finally all generated Akoin is burned.
function removeLiquidityAndBurn(uint256 amount) public onlyOwner() {
    require(lastLiquidityBurn.add(minLiquidityBurnInterval) < block.number, "Too Soon");
    lastLiquidityBurn = lastLiquidityBurn.add(minLiquidityBurnInterval);

    uint256 balance = IERC20(uniswapV2Pair).balanceOf(address(this));
    require(amount > 0 && amount < balance.mul(maxLiquidityBurnPercentage).div(10**2));

    uint256 prevAkoinBal = balanceOf(address(this));

    uniswapV2Router.removeLiquidity(
        address(this),
        address(wbnb),
        amount,
        0,
        0,
        address(this),
        block.timestamp
    );

    uint256 wbnbBalance = wbnb.balanceOf(address(this));
    if (wbnbBalance > 0) {
        address[] memory path = new address[](2);
        path[0] = address(wbnb);
        path[1] = address(this);
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            wbnbBalance,
            0,
            path,
            address(this),
            block.timestamp
        );
    }
    uint256 AkoinBal = balanceOf(address(this));
    uint256 toBurn = AkoinBal.sub(prevAkoinBal);
    require(toBurn > 0, "Nothing to burn");

    _burnFrom(address(this), toBurn);
    emit RemoveLiquidityAndBurn(toBurn);
}

function includeInReward(address account) external onlyOwner() {
    require(_isExcluded[account], "Account is already excluded");
    for (uint256 i = 0; i < _excluded.length; i++) {
        if (_excluded[i] == account) {
            _excluded[i] = _excluded[_excluded.length - 1];
            _tOwned[account] = 0;
            _isExcluded[account] = false;
            _excluded.pop();
            break;
        }
    }
}
    function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
    (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
    _tOwned[sender] = _tOwned[sender].sub(tAmount);
    _rOwned[sender] = _rOwned[sender].sub(rAmount);
    _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
    _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);        
    _takeLiquidity(tLiquidity);
    _reflectFee(rFee, tFee);
    emit Transfer(sender, recipient, tTransferAmount);
}

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

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

function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
    _taxFee = taxFee;
}

function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
    _liquidityFee = liquidityFee;
}

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

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

 //to recieve ETH from uniswapV2Router when swaping
receive() external payable {}

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

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

function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
    uint256 tFee = calculateTaxFee(tAmount);
    uint256 tLiquidityAndBurn = calculateLiquidityAndBurnFee(tAmount);
    uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidityAndBurn);
    return (tTransferAmount, tFee, tLiquidityAndBurn);
}

function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidityAndBurn, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
    uint256 rAmount = tAmount.mul(currentRate);
    uint256 rFee = tFee.mul(currentRate);
    uint256 rLiquidityAndBurn = tLiquidityAndBurn.mul(currentRate);
    uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidityAndBurn);
    return (rAmount, rTransferAmount, rFee);
}

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

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

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

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

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

function removeAllFee() private {
    if(_taxFee == 0 && _liquidityFee == 0) return;
    
    _previousTaxFee = _taxFee;
    _previousLiquidityFee = _liquidityFee;
    
    _taxFee = 0;
    _liquidityFee = 0;
}

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

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

function _approve(address owner, address spender, uint256 amount) private {
    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 _transfer(
    address from,
    address to,
    uint256 amount
) private {
    require(from != address(0), "ERC20: transfer from the zero address");
    require(to != address(0), "ERC20: transfer to the zero address");
    require(amount > 0, "Transfer amount must be greater than zero");
    if(from != owner() && to != owner())
        require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
    
    if(to == BURN_ADDRESS) {
        _burnFrom(from, amount);
        return;
    }

    // is the token balance of this contract address over the min number of
    // tokens that we need to initiate a swap + liquidity lock?
    // also, don't get caught in a circular liquidity event.
    // also, don't swap & liquify if sender is uniswap pair.
    uint256 contractTokenBalance = balanceOf(address(this));
    
    if(contractTokenBalance >= _maxTxAmount)
    {
        contractTokenBalance = _maxTxAmount;
    }
    
    bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;
    if (
        overMinTokenBalance &&
        !inSwapAndLiquify &&
        from != uniswapV2Pair
    ) {
        contractTokenBalance = numTokensSellToAddToLiquidity;
        //add liquidity
        swapAndLiquify(contractTokenBalance);
    }
    
    //indicates if fee should be deducted from transfer
    bool takeFee = true;
    
    //if any account belongs to _isExcludedFromFee account then remove the fee
    if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
        takeFee = false;
    }
    
    //transfer amount, it will take tax, burn, liquidity fee
    _tokenTransfer(from,to,amount,takeFee);
}
function _burnFrom(address sender, uint256 rAmount) private {
    uint256 rAccountBalance = _rOwned[sender];
    uint256 tAccountBalance = _tOwned[sender];
    uint256 tAmount = tAccountBalance.mul(rAmount).div(rAccountBalance);
    require(rAccountBalance >= rAmount, "ERC20: burn amount exceeds balance");
    _rOwned[sender] = rAccountBalance.sub(rAmount);
    _tOwned[sender] = tAccountBalance.sub(tAmount);
    _tTotal = _tTotal.sub(tAmount); // Take tokens out of circulation
    _rTotal = _rTotal.sub(rAmount);
    
    emit Transfer(sender, BURN_ADDRESS, rAmount);
}

function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
    // burn burnFee
    if (_burnFee > 0){
        uint256 burnFee = contractTokenBalance.mul(_burnFee).div(_burnFee.add(_liquidityFee));
        contractTokenBalance = contractTokenBalance.sub(burnFee);
        _burnFrom(address(this), burnFee);
    }
    if(!swapAndLiquifyEnabled){
        return;
    }
    // split the contract balance into halves
    uint256 half = contractTokenBalance.div(2);
    uint256 otherHalf = contractTokenBalance.sub(half);

    // capture the contract's current ETH balance.
    // 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
    // has been manually sent to the contract
    uint256 initialBalance = address(this).balance;

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

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

    // add liquidity to uniswap
    addLiquidity(otherHalf, newBalance);
    
    emit SwapAndLiquify(half, newBalance, otherHalf);
}

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] = address(wbnb);

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

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

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

    // add the liquidity
    uniswapV2Router.addLiquidity(
        address(this),
        address(wbnb),
        tokenAmount,
        ethAmount,
        0, // slippage is unavoidable
        0, // slippage is unavoidable
        address(this),
        block.timestamp
    );
}

//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
    if(!takeFee)
        removeAllFee();
    
    if (_isExcluded[sender] && !_isExcluded[recipient]) {
        _transferFromExcluded(sender, recipient, amount);
    } else if (!_isExcluded[sender] && _isExcluded[recipient]) {
        _transferToExcluded(sender, recipient, amount);
    } else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
        _transferStandard(sender, recipient, amount);
    } else if (_isExcluded[sender] && _isExcluded[recipient]) {
        _transferBothExcluded(sender, recipient, amount);
    } else {
        _transferStandard(sender, recipient, amount);
    }
    
    if(!takeFee)
        restoreAllFee();
}

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

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

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

}

Hi @CryptoBaba , welcome to the OZ forums. Please create a new topic for new questions.
You should start by following OpenZeppelin Upgrades: Step by Step Tutorial for Hardhat to set up your dev environment.

From there, use what you learned to deploy this contract. To verify I use hardhat verify Error verifying proxy with plugin @nomiclabs/hardhat-etherscan
It is extremely difficult to verify complex contracts on etherscan.

1 Like

Please refer to

It’s either SwapAndLiquify needs to be set to False or MaxTxPercent needs to be set to 100.

If you have rejected ownership then you likely cannot get the liquidity back.