1

I created this contract to simulate a liquidity pool and I'm testing it with the Remix IDE. I can say it works fine, except for the function to swap tokens for ether, which is bothering me. The user here has an amount of tokens and want to swap them for some ether. The approve function needs to be called so the LP contract is allowed to withdraw tokens from the user's wallet (first function in the figure below). By the way this is the ERC20 template from OpenZeppelin with minor changes, but none to the approve function.

remix

Anyway, I'm trying to execute the approve within the swap function. Everything seems correct, except it doesn't work ... I don't have any idea why. I need some help. Thanks!

function swapTokenforETH(uint256 tokenAmount) external { 
    lme = lmeContract(lmeAdress);
     // Compute the amount of ETH the user will receive
    address user = msg.sender;
    address lp = address(this);
    
    uint256 ethAmount = lp.balance - _k/(tokenSupply + tokenAmount);
    require(ethAmount > 0, "ethAmount <= 0");

    // Verify if the amount of ETH in LP is enough to continue the transaction   
    require(lp.balance >= ethAmount, "Insufficient ETH balance to complete the transaction (LP side)");

    // Verify if the amount of token of the user is enough to continue the transaction   
    require(lme.balanceOf(user) >= tokenAmount, "Insufficient token balance to complete the transaction (user side)"); 

    // User send the tokens to LP (user needs to approve allowance for this address in the main function)
    //IERC20(lmeAdress).approve(lp, tokenAmount);    // DIDN'T WORK 
    //lme.approve(lp, tokenAmount);    // DIDN'T WORK TOO  
    require(lme.transferFrom(user, lp, tokenAmount), "Critical failure");   
    updateTokenBalance();
        
    // LP transfer ETH to user
    payable(user).transfer(ethAmount);
} 

The error:

transact to LiquidityPool.swapTokenforETH errored: Error occurred: revert.

revert
    The transaction has been reverted to the initial state.
Error provided by the contract:
ERC20InsufficientAllowance
Parameters:
{
 "spender": {
  "value": "0x7b96aF9Bd211cBf6BA5b0dd53aa61Dc5806b6AcE",
  "documentation": "Address that may be allowed to operate on tokens without being their owner."
 },
 "allowance": {
  "value": "0",
  "documentation": "Amount of tokens a `spender` is allowed to operate with."
 },
 "needed": {
  "value": "1000",
  "documentation": "Minimum amount required to perform a transfer."
 }
}
Debug the transaction to get more information.

1 Answer 1

1

It seems like you are trying to approve from the contract address, meaning that your contract is approving the lp to take the tokens. When in reality you want the user to call approve before calling your swap function.

Even if you are approving first from the user, since your swap contract is the one calling transferFrom(), it is the one that needs to be approved, not your lp contract.

  1. User calls approve(< swap contract address >, < amount >)
  2. User calls swapTokenForETH(< amount >), in which swap contract takes tokens from the user and transfers them to the lp.
3
  • 1
    Thanks for the reply! I don't think I follow. The "swap contract address" you defined is the main contract of the token? In my example the tokens are within the user's wallet. As I understand the command 'approve(< swap contract address >, < amount >)' will approve the swap contract (token contract I guess) to withdraw tokens from the sender, which in this case is the LP I think... so noone is touching the user. I don't get it.
    – Integral
    Apr 2 at 22:38
  • 1
    @Integral No, swap contract address is the contract that contains the swapTokenForETH() function. Anytime a contract uses transferFrom() on behalf of a user, it needs to first be approved by that user. You can view the current allowance with allowance(user address, swap contract address).
    – Rohan Nero
    Apr 3 at 14:49
  • 1
    Okay, this is in line with what I did to make the transaction work in the end. So when someone makes a swap using Metamask, for example, Metamask intermediates the call to execute the approve function of the token contract and then intermediates the call to the swapTokenForETH function of the LP contract.
    – Integral
    Apr 4 at 0:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.