2

Hi,I had referred to this article and now I want to test swap dai to eth with syncswap api.

But I also get the insufficient funds error, actually, there's enough eth and dai in the wallet.

//balances

0.14671552290491718 ETH
274859749945138530 DAI
//erros

ERRORS: Error: insufficient funds for intrinsic transaction cost [ See: https://links.ethers.org/v5-errors-INSUFFICIENT_FUNDS ] (error={"reason":"processing response error","code":"SERVER_ERROR","body":"{\"jsonrpc\":\"2.0\",\"error\":{\"code\":3,\"message\":\"Failed to submit transaction: insufficient funds for gas + value. balance: 146715522904917175, fee: 3500000000000000000, value: 172989943652341920000000000000000000\",\"data\":{\"code\":104,\"message\":\"insufficient funds for gas + value. balance: 146715522904917175, fee: 3500000000000000000, value: 172989943652341920000000000000000000\"}},\"id\":56}\n","error":{"code":3,"data":{"code":104,"message":"insufficient funds for gas + value. balance: 146715522904917175, fee: 3500000000000000000, value: 172989943652341920000000000000000000"}},"requestBody":"{\"method\":\"eth_sendRawTransaction\"....
  • value means the dai amount I want to transfer.

  • Swap Dai For Eth codes

// JavaScript

public static async swapDaiToEth(daiAddress: string, wETHAddress: string) {
  // The factory of the Classic Pool.
  const classicPoolFactory: Contract = new Contract(
      this.classicPoolFactoryAddress,
      this.classicPoolFactoryAbi,
      this.provider
  );

  // Gets the address of the ETH/DAI Classic Pool.
  // wETH is used internally by the pools.
  const poolAddress: string = await classicPoolFactory.getPool(daiAddress, wETHAddress);

  // Checks whether the pool exists.
  if (poolAddress === ZERO_ADDRESS) {
      throw Error('Pool not exists');
  }

  // Gets the reserves of the pool.
  const pool: Contract = new Contract(poolAddress, this.poolAbi, this.provider);
  const reserves: [BigNumber, BigNumber] = await pool.getReserves(); // Returns tuple (uint, uint)

  // Sorts the reserves by token addresses.
  const [reserveETH, reserveDAI] = wETHAddress < daiAddress ? reserves : [reserves[1], reserves[0]];

  // The input amount of ETH
  const value = 100000000;

  // Constructs the swap paths with steps.
  // Determine withdraw mode, to withdraw native ETH or wETH on last step.
  // 0 - vault internal transfer
  // 1 - withdraw and unwrap to naitve ETH
  // 2 - withdraw and wrap to wETH
  const withdrawMode = 1; // 1 or 2 to withdraw to user's wallet

  const swapData: string = defaultAbiCoder.encode(
      ["address", "address", "uint8"],
      [daiAddress, this.signer.address, withdrawMode], // tokenIn, to, withdraw mode
  );

  // We have only 1 step.
  const steps = [{
      pool: poolAddress,
      data: swapData,
      callback: ZERO_ADDRESS, // we don't have a callback
      callbackData: '0x',
  }];

  // If we want to use the native ETH as the input token,
  // the `tokenIn` on path should be replaced with the zero address.
  // Note: however we still have to encode the wETH address to pool's swap data.
  const nativeETHAddress = ZERO_ADDRESS;

  // We have only 1 path.
  const paths = [{
      steps: steps,
      tokenIn: daiAddress,
      amountIn: value,
  }];

  // Gets the router contract.
  const router: Contract = new Contract(this.routerAddress, this.routerAbi, this.provider);

  // Note: checks approval for ERC20 tokens.
  // The router will handle the deposit to the pool's vault account.
  const response = await router.swap(
      paths, // paths
      0, // amountOutMin // Note: ensures slippage here
      BigNumber.from(Math.floor(Date.now() / 1000)).add(1800), // deadline // 30 minutes
      {
          value: value,
      }
  );

  await response.wait();
}

Thanks.

2 Answers 2

2

I share with you the working code. I can swap between ETH and DAI on SyncSwap Era Testnet.

I tried this on ETH/USDC, but it's not working for large amount of USDC, only small amount. I think that maybe the pool is not enough liquidity and we had to split the token in amount and find routes to swap.

async function syncSwapETHUSDC(account: WalletAccount, amountStr: string, direction: number = 0) {
    const wETHAddress = Constants.getSyncSwapWETHArrd()
    const usdcAddress = Constants.getUSDCAddress()
    const routerAddress = Constants.getSyncSwapRouterAddress()
    const classicPoolFactoryAddress = Constants.getSyncSwapClassicPoolFactoryAddress()
    const classicPoolFactoryAbi = require("../abi/SyncSwapClassicPoolFactoryABI.json")
    const routerAbi = require("../abi/SyncSwapRouterABI.json");

    const signer = new zksync.Wallet("privateKey", zkSyncProvider, ethProvider)

    var tokenInAddress = ""
    var amount: ethers.BigNumber

    if (direction == 0) {
        tokenInAddress = wETHAddress
        amount = ethers.utils.parseEther(amountStr)
    } else {
        tokenInAddress = usdcAddress
        amount = ethers.utils.parseUnits(amountStr, 6)
        console.log(ethers.utils.formatUnits(amount, 6))
        
        const usdcContract = new ethers.Contract(usdcAddress, zksync.utils.IERC20, signer)
        console.log("----")
        let allowedAmount: ethers.BigNumber = await usdcContract.allowance(signer.address, routerAddress)
        console.log(ethers.utils.formatUnits(allowedAmount, 6))

        if (allowedAmount.lte(amount)) {
            
            let approveTx = await usdcContract.approve(routerAddress, amount)
            await approveTx.wait()
        } 
    }
    console.log(tokenInAddress)
    // The factory of the Classic Pool.
    const classicPoolFactory = new zksync.Contract(
        classicPoolFactoryAddress,
        classicPoolFactoryAbi,
        zkSyncProvider
    );

    // Gets the address of the ETH/USDC Classic Pool.
    // wETH is used internally by the pools.
    const poolAddress = await classicPoolFactory.getPool(wETHAddress, usdcAddress);

    // Checks whether the pool exists.
    if (poolAddress === ethers.constants.AddressZero) {
        console.log('pool not exists')
        return
    }

   
    const withdrawMode = 1; // 1 or 2 to withdraw to user's wallet

    const swapData: string = ethers.utils.defaultAbiCoder.encode(
        ["address", "address", "uint8"],
        [tokenInAddress, signer.address, withdrawMode], // tokenIn, to, withdraw mode
    );

    const steps = [{
        pool: poolAddress,
        data: swapData,
        callback: ethers.constants.AddressZero,
        callbackData: '0x',
    }];


    const paths = [{
        steps: steps,
        tokenIn: (direction == 0) ? ethers.constants.AddressZero : tokenInAddress,
        amountIn: amount,
    }];
    console.log(paths)

    const router = new zksync.Contract(routerAddress, routerAbi, signer);

    const response = await router.swap(
        paths, // paths
        0, // amountOutMin // Note: ensures slippage here
        ethers.BigNumber.from(Math.floor(Date.now() / 1000)).add(1800), // deadline // 30 minutes
        {
            //value: amount, // please uncomment this if your token in is ETH
            gasLimit: 14000000
        }
    );

    let tx = await response.wait();
    console.log(tx.transactionHash)
}
1
  • It's great, thanks so much. If you have some spare time, could you teach me how to add and remove pools? I had read this article, but without examples,I don't know how to use these functions correctly. Thanks.
    – SylorHuang
    Commented Apr 6, 2023 at 12:37
1

This error message you received indicates that there is not enough ETH in your account to cover the transaction fees.

You need to either add more ETH to your account or reduce the value being transferred in the transaction.

1
  • I don't think so. I think eth 0.146 is enough for gas. And I swap dai for eth in Website page, the gas is not as high. Maybe some wrong with the swap codes.
    – SylorHuang
    Commented Apr 1, 2023 at 12:57

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.