0

Getting this error when attempting to call an external swap function in a contract I created on the Sepolia Test Network from Hardhat TypeScript.

  reason: 'execution reverted: ERC20: transfer amount exceeds allowance', 
  code: 'UNPREDICTABLE_GAS_LIMIT',
  method: 'estimateGas'

Typescript is:

import { ethers, network } from "hardhat";
import { abi as abiSwapContract } from "../artifacts/contracts/SwapDex.sol/SwapDex.json";


const SWAP_CONTRACT_ADDRESS = "0x932A674C2C518325EF728630b72C9F3e91c3CF16";
const TOKEN0_NAME = "USDC";
const TOKEN0_ADDRESS = "0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8";
const TOKEN1_NAME = "DAI";
const TOKEN1_ADDRESS = "0x82fb927676b53b6eE07904780c7be9b4B50dB80b";
const ROUTER_ADDRESS = "0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008";


async function main() {

const [deployer] = await ethers.getSigners();
console.log("Deployer Account Address: \t", await deployer.getAddress());
const deployerBalance = (await deployer.getBalance()).toString();
console.log("Signer Account balance: \t", deployerBalance);

const contractSwapDex = new ethers.Contract(
    SWAP_CONTRACT_ADDRESS,
    abiSwapContract,
    deployer
  );

  const outputAmount = await contractSwapDex.swapTokens("1","1",TOKEN0_NAME,TOKEN0_ADDRESS,
  500000000,6,TOKEN1_NAME,TOKEN1_ADDRESS,0,18,"UniswapV2","UniswapV2","SELL",30,ROUTER_ADDRESS,
  500);


  console.log(outputAmount);


}

// Error Handling 
main().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});

My hardhat configuration is:

 sepolia_test: {
  url: sepolia_test_provider_url,
  chainId: 11155111,
  accounts: [private_key_test_account],
  gas: 2100000,
  gasPrice: 8000000000,
},

I am running the typescript with this node hardhat command:

npx hardhat run scripts/swapDex.ts --network sepolia_test

I am unclear with this setup how gas fees are being charged and paid. Does it just default to Sepolia ETH being paid out the metamask wallet's test account? Or is it charging it to money in the contract that I'm calling? Even when I transferred 1 USDC into the contract that I'm calling the function in, it still gave me the exception about unpredicable gas limit and that the transfer amount exceeds allowance. Metamask has both Sepolia Ether and USDC in it.

1 Answer 1

2

You're facing this error because you haven't approved the Swap contract to spend the amount of tokens (particularly token0 i.e., USDC in your case) that you're swapping. You can check that by comparing the amount to be swapped with the current allowance.

You can do that by defining the ABI for approve() and allowance() functions and calling the same using the USDC contract, like this:


const amountToSwap = ethers.parseUnits("1"); // Means 1 ether (i.e., 1 USDC in your case)

const erc20_approveAndAllowance_abi = [
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "owner",
                "type": "address"
            },
            {
                "internalType": "address",
                "name": "spender",
                "type": "address"
            }
        ],
        "name": "allowance",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "spender",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "amount",
                "type": "uint256"
            }
        ],
        "name": "approve",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "nonpayable",
        "type": "function"
    }
]

const token0_contract = new ethers.Contract(TOKEN0_ADDRESS, erc20_approveAndAllowance_abi, deployer);

const token0_allowance = await token0_contract.allowance(await deployer.getAddress(), SWAP_CONTRACT_ADDRESS);

if (token0_allowance < amountToSwap) {
    console.log("Allowance before approval: ", token0_allowance.toString());

    token0_contract.approve(SWAP_CONTRACT_ADDRESS, amountToSwap).then(async (tx) => {
        const receipt = await tx.wait()
    
        console.log("Tx hash of approval: ", receipt.hash)
    
        token0_contract.allowance(await deployer.getAddress(), SWAP_CONTRACT_ADDRESS).then((allowance) => {
            console.log("Allowance after approval: ", allowance.toString())
        })
    })
  
}

Now, you can proceed with the calling of swapTokens() function.

3
  • Thanks so much, Syed. That was exactly it! :) Commented Apr 28 at 8:27
  • You’re welcome, Ian. Happy to help! Commented Apr 28 at 8:48
  • Kindly please accept the answer, if it solved your problem. Commented Apr 28 at 8:49

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.