Inheritance Issue - "Safemath Identifier already declared"

Hello,
So I was working on this reflection contract but have hit a bit of a conundrum.

My uniswapv2router02 parent contains an instance of `using SafeMath for uint256;`, while my main contract also contains an instance of using SafeMath for uint256;

This results in a failed compile returning the following:

DeclarationError: Identifier already declared.
  --> /C/Users/xxxxx/sc20210716_01/contracts/NJP.sol:11:1:
   |
11 | import "@uniswap/uniswap-v2-periphery-master/contracts/UniswapV2Router02.sol";
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: The previous declaration is here:
 --> @openzeppelin/contracts/token/ERC20/IERC20.sol:8:1:
  |
8 | interface IERC20 {
  | ^ (Relevant source part starts here and spans across multiple lines).

,DeclarationError: Identifier already declared.
  --> /C/Users/xxxxx/sc20210716_01/contracts/NJP.sol:11:1:
   |
11 | import "@uniswap/uniswap-v2-periphery-master/contracts/UniswapV2Router02.sol";
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: The previous declaration is here:
  --> @openzeppelin/contracts/utils/math/SafeMath.sol:15:1:
   |
15 | library SafeMath {
   | ^ (Relevant source part starts here and spans across multiple lines).

Compilation failed. See above.
Truffle v5.3.14 (core: 5.3.14)
Node v14.17.1

Is there a known work around for this?




SOURCE:


// SPDX-License-Identifier: MIT

pragma solidity >=0.6.12;

import "@openzeppelin/contracts/access/Ownable.sol";

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "@openzeppelin/contracts/utils/Address.sol";

import "@openzeppelin/contracts/utils/Context.sol";

import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";

import "@uniswap/uniswap-v2-periphery-master/contracts/UniswapV2Router02.sol";

//----------------------------------------------------------------------------------------------------

//NJP CONTRACT

contract NJP is Context, IERC20, Ownable {

    using SafeMath for uint256;

    using Address for address;

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//GLOBAL MAPPINGS AND VARIABLES

    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 = "NJP";

    string private _symbol = "NJP";

    uint8 private _decimals = 9;

    uint256 public _taxFee = 5;

    uint256 private _previousTaxFee = _taxFee;

    uint256 public _liquidityFee = 5;

    uint256 private _previousLiquidityFee = _liquidityFee;

    IUniswapV2Router02 public immutable uniswapV2Router;

    address public immutable uniswapV2Pair;

    bool inSwapAndLiquify;

    bool public swapAndLiquifyEnabled = true;

    uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9;

    uint256 public numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9;

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//CONTRACT EVENTS

    event TaxFeeUpdated(uint256 taxFee);

    event LiquidityFeeUpdated(uint256 liquidityFee);

    event ExcludeFromRewardUpdated(address account);

    event IncludeInRewardUpdated(address account);

    event ExcludeFromFeeUpdated(address account);

    event IncludeInFeeUpdated(address account);

    event MaxTxAmountUpdated(uint _maxTxAmount);

    event SwapAndLiquifyEnabledUpdated(bool enabled);

    event NumTokensSellToAddToLiquidityUpdated(uint256 _numTokensSellToAddToLiquidity);

    event SwapAndLiquify(

        uint256 tokensSwapped,

        uint256 ethReceived,

        uint256 tokensIntoLiqudity

    );

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//TIME LOCK

    modifier lockTheSwap {

        inSwapAndLiquify = true;

        _;

        inSwapAndLiquify = false;

    }

    enum Lock {

      TAX_FEE,

      LIQUIDITY_FEE,

      EXCLUDE_FROM_REWARD,

      INCLUDE_IN_REWARD,

      EXCLUDE_FROM_FEE,

      INCLUDE_IN_FEE,

      MAX_TX,

      SWAP_AND_LIQUIFY_ENABLED,

      NUM_TOKENS_SELL_TO_ADD_TO_LIQUIDITY

    }

    uint256 private constant _TIMELOCK = 1 days;

    mapping(Lock => uint256) public timelocks;

    modifier unlocked(Lock _lock) {

      require(timelocks[_lock] != 0 && timelocks[_lock] <= block.timestamp, "Function is timelocked");

      _;

      timelocks[_lock] = 0;

    }

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//CONSTRUCTOR

constructor () public {

        _rOwned[_msgSender()] = _rTotal;

        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);

         // Create a uniswap pair for this new token

        uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())

            .createPair(address(this), _uniswapV2Router.WETH());

        // set the rest of the contract variables

        uniswapV2Router = _uniswapV2Router;

        //exclude owner and this contract from fee

        _isExcludedFromFee[owner()] = true;

        _isExcludedFromFee[address(this)] = true;

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

    }

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//ERC20 STANDARDS

    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;

    }

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//REWARD -- REFLECTIONS -- FEES -- TAXES

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 unlocked(Lock.EXCLUDE_FROM_REWARD) {

        require(!_isExcluded[account], "Account is already excluded");

        if(_rOwned[account] > 0) {

            _tOwned[account] = tokenFromReflection(_rOwned[account]);

        }

        _isExcluded[account] = true;

        _excluded.push(account);

        emit ExcludeFromRewardUpdated(account);

    }

function includeInReward(address account) external onlyOwner unlocked(Lock.INCLUDE_IN_REWARD) {

        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;

            }

        }

        emit IncludeInRewardUpdated(account);

    }

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 unlocked(Lock.EXCLUDE_FROM_FEE) {

        _isExcludedFromFee[account] = true;

        emit ExcludeFromFeeUpdated(account);

    }

function includeInFee(address account) public onlyOwner unlocked(Lock.INCLUDE_IN_FEE) {

        _isExcludedFromFee[account] = false;

        emit IncludeInFeeUpdated(account);

    }

function setTaxFeePercent(uint256 taxFee) external onlyOwner unlocked(Lock.TAX_FEE) {

        require(taxFee <= 15, "Amount must be less than or equal to 15");

        _taxFee = taxFee;

        emit TaxFeeUpdated(taxFee);

    }

function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner unlocked(Lock.LIQUIDITY_FEE) {

        require(liquidityFee <= 15, "Amount must be less than or equal to 15");

        _liquidityFee = liquidityFee;

        emit LiquidityFeeUpdated(liquidityFee);

    }

function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner unlocked(Lock.MAX_TX) {

        require(maxTxPercent > 0, "Amount must be greater than 0");

        _maxTxAmount = _tTotal.mul(maxTxPercent).div(

            10**2

        );

        emit MaxTxAmountUpdated(_maxTxAmount);

    }

function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner unlocked(Lock.SWAP_AND_LIQUIFY_ENABLED) {

        swapAndLiquifyEnabled = _enabled;

        emit SwapAndLiquifyEnabledUpdated(_enabled);

    }

function setNumTokensSellToAddToLiquidity(uint256 _numTokensSellToAddToLiquidity) external onlyOwner unlocked(Lock.NUM_TOKENS_SELL_TO_ADD_TO_LIQUIDITY) {

      numTokensSellToAddToLiquidity = _numTokensSellToAddToLiquidity;

      emit NumTokensSellToAddToLiquidityUpdated(_numTokensSellToAddToLiquidity);

    }

     //to recieve ETH from uniswapV2Router when swapping

    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 tLiquidity) = _getTValues(tAmount);

        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate());

        return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);

    }

function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {

        uint256 tFee = calculateTaxFee(tAmount);

        uint256 tLiquidity = calculateLiquidityFee(tAmount);

        uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity);

        return (tTransferAmount, tFee, tLiquidity);

    }

function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) {

        uint256 rAmount = tAmount.mul(currentRate);

        uint256 rFee = tFee.mul(currentRate);

        uint256 rLiquidity = tLiquidity.mul(currentRate);

        uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity);

        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 calculateLiquidityFee(uint256 _amount) private view returns (uint256) {

        return _amount.mul(_liquidityFee).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];

    }

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//INTERNAL (PRIVATE)

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.");

        // 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 &&

            swapAndLiquifyEnabled

        ) {

            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);

    }

//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------

//UNISWAP FUNCTIONS

    function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {

        // 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] = uniswapV2Router.WETH();

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

        // make the swap

        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(

            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.addLiquidityETH{value: ethAmount}(

            address(this),

            tokenAmount,

            0, // slippage is unavoidable

            0, // slippage is unavoidable

            address(0),

            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 tLiquidity) = _getValues(tAmount);

        _rOwned[sender] = _rOwned[sender].sub(rAmount);

        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);

        _takeLiquidity(tLiquidity);

        _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);

    }

    function unlock(Lock _lock) public onlyOwner {

      timelocks[_lock] = block.timestamp + _TIMELOCK;

    }

    function lock(Lock _lock) public onlyOwner {

      timelocks[_lock] = 0;

    }}

//----------------------------------------------------------------------------------------------------