Importing Parent Contract "Identifier not found or not unique"

I am just trying to Import the parent to the child and implement it
as:

import "contracts/ALT_Token.sol";

contract Ethereum_Exchange is ALT_Token {

, but receive "Identifier not found or not unique".

Both Contracts are in the same truffle framework contracts folder. It is NOT something trivial like a name typo or changing the forward slash to a back slash of the import string.

Any ideas?

Source Code:

PARENT

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

contract ALT_Token {

    

mapping(address => uint256) private _balances;

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

string private _name = "ALT_Token";

string private _symbol = "ALT$";

uint256 private _totalSupply = 0;

event Transfer(address indexed from, address indexed to, uint256 value);

event Approval(address indexed owner, address indexed spender, uint256 value);

//TOKEN CREATION

   function _mint(address account, uint256 amount) internal virtual {

        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply += amount;

        _balances[account] += amount;

        emit Transfer(address(0), account, amount);

              }

    

    constructor () {

        _mint(address(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4), 2020000*10**18);

    }

    function name() public view returns (string memory) {

        return _name;

     }

    function symbol() public view virtual returns (string memory) {

        return _symbol;

     }

    function decimals() public view virtual returns (uint8) {

        return 18;

     }

    function totalSupply () public view virtual returns (uint256) {

        return _totalSupply;

     }

    function balanceOf(address account) public view virtual returns (uint256) {

        return _balances[account];

     }

    function transfer(address recipient, uint256 amount) public virtual returns (bool) {

        _transfer(_msgSender(), recipient, amount);

        return true;

            }

            

     function transferFrom(address sender, address recipient, uint256 amount) public virtual returns (bool) {

        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];

        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");

        unchecked {

            _approve(sender, _msgSender(), currentAllowance - amount);

        }

        return true;

     }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {

            _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);

            return true;

        }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {

        uint256 currentAllowance = _allowances[_msgSender()][spender];

        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");

        unchecked {

            _approve(_msgSender(), spender, currentAllowance - subtractedValue);

        }

        return true;

     }

    function _transfer (address sender, address recipient, uint256 amount) internal virtual {

        require(sender != address(0), "ERC20: transfer from the zero address");

        require(recipient != address(0), "ERC20: transfer to the zero address");

        

        uint256 senderBalance = _balances[sender];

        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");

        unchecked {

            _balances[sender] = senderBalance - amount;

        }

        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

     }  

    

    function _msgSender() internal view virtual returns (address) {

        return msg.sender;

     }

    function _approve(address owner, address spender, uint256 amount) internal virtual {

            require(owner != address(0), "ERC20: approve from the zero address");

            require(spender != address(0), "ERC20: approve to the zero address");

            _allowances[owner][spender] = amount;

            emit Approval(owner, spender, amount);

        }

    function _burn(address account, uint256 amount) internal virtual {

        require(account != address(0), "ERC20: burn from the zero address");

        uint256 accountBalance = _balances[account];

        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");

        unchecked {

            _balances[account] = accountBalance - amount;

        }

        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        

     }

}



CHILD
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import "contracts/ALT_Token.sol";

contract Ethereum_Exchange is ALT_Token {

  string public name = "Ethereum Exchange";

    uint public rate = 100;

  event TokensPurchased(

    address account,

    address token,

    uint amount,

    uint rate

   );

  event TokensSold(

    address account,

    address token,

    uint amount,

    uint rate

   );

    

  constructor(ALT_Token _token) public {

    token = _token;

  }

  function buyTokens() public payable {

       uint tokenAmount = msg.value * rate;

    require(token.balanceOf(address(this)) >= tokenAmount);

    token.transfer(msg.sender, tokenAmount); 

    emit TokensPurchased(msg.sender, address(token), tokenAmount, rate);

  }

  function sellTokens(uint _amount) public {

    require(token.balanceOf(msg.sender) >= _amount);    

    uint etherAmount = _amount / rate;   

    require(address(this).balance >= etherAmount);

    token.transferFrom(msg.sender, address(this), _amount);

    msg.sender.transfer(etherAmount); 

    emit TokensSold(msg.sender, address(token), _amount, rate);

  }

}

You should use a relative import when importing a file that's inside your contracts/ directory:

import "./ALT_Token.sol";

Direct imports with paths relative to your project root (like contracts/ALT_Token.sol) are disallowed in Truffle as of v5.4.2. They never really worked reliably and after a recent change to stop using absolute paths (which were ending up in contract metadata) could not be reconciled with how Truffle tracks files internally. They can always be replaced with equivalent relative imports anyway. See #4190 if you want details.

1 Like

Actually, the error message you posted indicates that you might be running into a slightly different problem. Identifier not found or not unique comes from the compiler (rather than Truffle itself) and in this particular situation means that the compiler successfully processed the import but did not find ALT_Token in the file. If you're running an earlier version of Truffle, it might be allowing the import but resolving it incorrectly. So switching to a relative one might help anyway. If that's what happening here then you're experiencing one of the reasons why such imports are now disallowed in Truffle :slight_smile: