Add Liquidity failed: cannot estimate gas - NEW TOKENS - it is NOT gas issue

Hi everyone,

I created my own Token and added some functions like addWhiteList and Staking. The contract work flawless and smooth on remix, i integrated it to a Flutter App for android in iOS and everything work fine! but when i go to an exchange i notice that i could not add liquidity to the Token getting the following error:

"Add Liquidity failed: cannot estimate gas; transaction may fail or may require manual gas limit [ See: ] (reason="execution reverted: TransferHelper::transferFrom: transferFrom failed", method="estimateGas" "

Yes i have enough gas, delete decimals, set only integers, etc.

Continuing with my research, i created a basic contract with the wonderful app "Token wizard", I loved it. And I realized that this token was eligible to add liquidity. When checking the differences I realized that I was not using the import libraries "@openzeppelin/contracts/token/ERC20/ERC20.sol", added the libraries to my contract, run a new deploy an walla! suddenly I could add liquidity to my new token BUT obviously im only able to use openzeppelin ERC20 functions and im no able to modify for example _mint even if i have a diferent ERC20.sol created on my project, when i call import "./ERC20.sol" i keep gettin the error:
" DeclarationError: Identifier already declared.
--> FuelBoxToken.sol:5:1:
5 | import "./ERC20.sol";
| ^^^^^^^^^^^^^^^^^^^^^
Note: The previous declaration is here:
--> @openzeppelin/contracts/utils/Context.sol:16:1:
16 | abstract contract Context {
| ^ (Relevant source part starts here and spans across multiple lines).

Please help me

I understand that the .dept/npm/openzepeline files can be modified but it is not a good practice and team must be attentive to new updates, i would prefer to keep those files as they are.

As you mentioned it did work with the erc20 contract of openzeppelin, which means you have an error in you code that is causing the issue.

As you have not provided any code and transaction information it’s impossible to tell what you are doing wrong. You statement of adding liquidity actually means even less as an erc20 token itself does not have a “liquidity” function. This means you are trying to do even something else for which you provided no information.

Now you want to change OpenZeppelin’s ERC20 implementation, however you have no idea what you did wrong initially with your token.
As for the double identifier error you are getting without again providing any info makes it really hard to help out.

If you want to change the ERC20 token behaviour then your best course of action is to extend it. Which you do by inheriting from it. If you require further help you will have to provide a lot more information.

1 Like

Found the error:

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

    uint256 currentAllowance = _allowances[sender][_msgSender()];
    require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
    unchecked {
        _approve(sender, _msgSender(), currentAllowance - amount);

    return true;

i just modified _msgSender() to recipient, in some way this is incorrect. Made it because i think _msgSender() = sender, so that makes no sense to me

Initialy i made the modify because actually works!

"uint256 currentAllowance = _allowances[sender][_msgSender()];" throw the error "ERC20: transfer amount exceeds allowance" when allowance do not exceeds allowance


"uint256 currentAllowance = _allowances[sender][recipient];" works smooth but generate the mentioned bug when your try tu add liquidity, maybe the way TransferFrom is called:

function stake(address contractAddress, uint256 amount, uint256 apyReceived) public virtual {
        require(_isStaking[contractAddress] == 1, "Can't stake on that contract");
        require(amount > 0, "Can't stake 0 tokens");
        require(_balances[msg.sender] >= amount, "Not enough tokens on balanace to stake");
        require(apyReceived > 0 && apyReceived < 4, "Selected apy is not correct");

        if(usersAddressStaking.length > 1){


        transferFrom(msg.sender, contractAddress, amount);

        if (apyReceived == 1) {
            apySelected[msg.sender] = APY_1_YEAR;
        } else if (apyReceived == 2) {
            apySelected[msg.sender] = APY_5_YEARS;
        } else if (apyReceived == 3) {
            apySelected[msg.sender] = APY_15_YEARS;

        if (stakes[msg.sender] == 0) {
        stakes[msg.sender] += amount;
        _totalStaked += amount;
        distributedRewardsTimeStamp[msg.sender] = block.timestamp;

thank your for your support :smiley:

Solved by replacin 'transferFrom(msg.sender, contractAddress, amount);' with transfer but is essential to approve amounts before calling stake function