Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot estimate gas on flash loan #51

Open
lucarducci opened this issue May 6, 2024 · 9 comments
Open

Cannot estimate gas on flash loan #51

lucarducci opened this issue May 6, 2024 · 9 comments

Comments

@lucarducci
Copy link

I have the following script to request a USD flash loan on Polygon blockchain:

import * as api from "@protocolink/api";
import * as common from "@protocolink/common";
import ethers from "ethers";
import dotenv from "dotenv";

// Config
dotenv.config();
let chainId = common.ChainId.polygon;
let loanToken = "USDC";
let amount = 1;
let network = "matic";
let account = process.env.ACCOUNT;
let mnemonic = process.env.MNEMONIC;

try {
  // Setup wallet

  let wallet = ethers.Wallet.fromMnemonic(mnemonic);
  let provider = new ethers.providers.InfuraProvider(network, process.env.INFURA_KEY);
  let signer = wallet.connect(provider);

  console.log("Start bot");

  // Get token list for loan
  const tokenList = await api.protocols.aavev3.getFlashLoanTokenList(chainId);
  let underlyingToken;
  for (let token of tokenList) {
    if (token.symbol == loanToken) {
      underlyingToken = token;
    }
  }

  const loans = [
    {
      token: underlyingToken,
      amount: amount.toString(),
    },
  ];

  // Create loan
  const flashLoanQuotation = await api.protocols.aavev3.getFlashLoanQuotation(chainId, {
    loans,
  });

  let i = underlyingToken.address;
  console.log(
    "Amount to repay: ",
    flashLoanQuotation.repays.tokenAmountMap[i].amount + " " + flashLoanQuotation.repays.tokenAmountMap[i].token.symbol
  );

  const [flashLoanLoanLogic, flashLoanRepayLogic] = api.protocols.aavev3.newFlashLoanLogicPair(loans);
  const logics = [flashLoanLoanLogic, flashLoanRepayLogic];

  // Build router data
  const routerData: api.RouterData = {
    chainId,
    account: account,
    logics: logics,
  };
  let estimateResult = await api.estimateRouterData(routerData, { permit2Type: "permit" });

  console.log(
    "FUNDS: ",
    estimateResult.funds.tokenAmountMap[i].amount + " " + estimateResult.funds.tokenAmountMap[i].token.symbol
  );
  console.log("FEE 1: ", estimateResult.fees[0].feeAmount.amount + " " + estimateResult.fees[0].feeAmount.token.symbol);
  console.log("FEE 2: ", estimateResult.fees[1].feeAmount.amount + " " + estimateResult.fees[0].feeAmount.token.symbol);

  // Increase fee
  estimateResult.fees[0].feeAmount.amount = (Number(estimateResult.fees[0].feeAmount.amount) * 20).toString();
  estimateResult.fees[1].feeAmount.amount = (Number(estimateResult.fees[1].feeAmount.amount) * 20).toString();

  // Approve
  for (const approval of estimateResult.approvals) {
    console.log("Approve ...");
    const txApprove = await signer.sendTransaction(approval);
    txApprove.wait();
    console.log("Gas limit: ", Number(txApprove.gasLimit));
  }

  // Permit
  if (estimateResult.permitData) {
    console.log("Sign ...");
    const permitSig = await signer._signTypedData(
      estimateResult.permitData.domain,
      estimateResult.permitData.types,
      estimateResult.permitData.values
    );
    // console.log("PermitSig", permitSig);
    routerData.permitData = estimateResult.permitData;
    routerData.permitSig = permitSig;
  } else {
    console.log("NOTHING TO SIGN");
  }

  // Execute
  console.log("Execute ...");
  const transactionRequest = await api.buildRouterTransactionRequest(routerData);

  console.log("Send ...");
  const tx = await signer.sendTransaction(transactionRequest);
  console.log(tx);
} catch (e) {
  console.error("ERROR: ", e.reason || e);
}

This is the output log:

Start bot
Amount to repay:  1.0005 USDC
FUNDS:  0.0005 USDC
FEE 1:  0.000667898340426478 MATIC
FEE 2:  0.000001335796680852 MATIC
Approve ...
Gas limit:  56107
Sign ...
Set fees
Execute ...
Send ...
ERROR:  cannot estimate gas; transaction may fail or may require manual gas limit

Why is it trowing this error on gas fees?

@zodahu
Copy link
Contributor

zodahu commented May 6, 2024

Hey @lucarducci, thank you for your question.

  • To understand why the transaction failed, you can use tools like Tenderly to simulate the to, data, value in the transactionRequest for clarification.
  • I suggest starting with a balancer flash loan for clarification, as it has a 0% flash loan fee, thus eliminating the need for the Approve & Permit process.

@lucarducci
Copy link
Author

Also with the balancer flash loan I get the 2 objects in approval and the permitData in the estimateResult. Is it normal?
I keep getting the same error.

How can I set a manual gas limit in protocolink?

@zodahu
Copy link
Contributor

zodahu commented May 6, 2024

  1. This is unusual. Did you implement newFlashLoanLogicPair similar to the example? If so, your routerData should look like this:"
{
  "chainId": 137,
  "account": "0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa",
  "logics": [
    {
      "rid": "balancer-v2:flash-loan",
      "fields": {
        "id": "6f6cc4d7-001f-4be8-a444-3f98abb9ba24",
        "loans": [
          {
            "token": {
              "chainId": 137,
              "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
              "decimals": 18,
              "symbol": "WMATIC",
              "name": "Wrapped Matic"
            },
            "amount": "10000"
          }
        ],
        "isLoan": true
      }
    },
    {
      "rid": "balancer-v2:flash-loan",
      "fields": {
        "id": "6f6cc4d7-001f-4be8-a444-3f98abb9ba24",
        "loans": [
          {
            "token": {
              "chainId": 137,
              "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
              "decimals": 18,
              "symbol": "WMATIC",
              "name": "Wrapped Matic"
            },
            "amount": "10000"
          }
        ],
        "isLoan": false
      }
    }
  ]
}
  1. Ethers.js’s signer.sendTransaction() allows to set both gasLimit and gasPrice.

@lucarducci
Copy link
Author

It worked adding transactionRequest.gasLimit = txApprove.gasLimit

Now I get the transaction completed with no errors but I can't see the tx in the blockchain explorer, it should be here:
https://polygonscan.com/tx/0xbb4fed62d09fa508b757a67ee1786f7be86214d233653996a98ba7f2800f338c

And also I don't see the few USDC that I should have paid from my wallet.
Am I missing something?

Below the full log of the result of the sendTransaction function:

{
  type: 2,
  chainId: 137,
  nonce: 100,
  maxPriorityFeePerGas: BigNumber { _hex: '0x59682f00', _isBigNumber: true },
  maxFeePerGas: BigNumber { _hex: '0x59682f3e', _isBigNumber: true },
  gasPrice: null,
  gasLimit: BigNumber { _hex: '0x01b656', _isBigNumber: true },
  to: '0xDec80E988F4baF43be69c13711453013c212feA8',
  value: BigNumber { _hex: '0x18cf45cf0201d3', _isBigNumber: true },
  data: '0xa1de453700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000ffff5a88840ff1f168e163acd771dfb292164cfa0000000000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001842b67b57000000000000000000000000053e09dd70e20a0b5ceaf2447484063dccbe3f2190000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000006660a8ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e544a364fb3412e25809aa882efd5b5d5ea36d100000000000000000000000000000000000000000000000000000000663a6d7f00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000041f9ce17b1431022eb169654c935a99bcdb94a5ce4a7f63de3422a315071da5d880e656f4b966ebdcb360513bf872233a0cb1d892f8fafa3310c72f6456a90a1711c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008436c7851600000000000000000000000053e09dd70e20a0b5ceaf2447484063dccbe3f2190000000000000000000000006e544a364fb3412e25809aa882efd5b5d5ea36d10000000000000000000000000000000000000000000000000000000000001ad90000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c33590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000663a6d8400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f81cf774052d03873b32944a036bf0647bfb5bf0000000000000000000000000000000000000000000000000000000000000964ab9c4b5d0000000000000000000000006f81cf774052d03873b32944a036bf0647bfb5bf00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000010000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104414bf3890000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000000640000000000000000000000006e544a364fb3412e25809aa882efd5b5d5ea36d10000000000000000000000000000000000000000000000000000000066391d2f00000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000970a1a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000989680000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000144c04b8d59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000006e544a364fb3412e25809aa882efd5b5d5ea36d10000000000000000000000000000000000000000000000000000000066391d2f00000000000000000000000000000000000000000000000000000000009890ac00000000000000000000000000000000000000000000000000000000009708a10000000000000000000000000000000000000000000000000000000000000042c2132d05d31c914a87c6611c10748aeb04b58e8f0000648f3cf7ad23cd3cadbd9735aff958023239c6a0630000643c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009890ac0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000006f81cf774052d03873b32944a036bf0647bfb5bf000000000000000000000000000000000000000000000000000000000098aa080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c33590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098aa080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000018becd5d414633616176652d76333a666c6173682d6c6f616e0000000000000000000000000000000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000107871c0bba07065726d6974323a70756c6c2d746f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fb20753f85f89be6f42d228667d70e62d1ba5f75000000000000000000002710000000000000000000000000000000000000000000000000000000000000004151991e886b4a7b7353154311fc5c451f6a91f78ad40333907e32b74fb1e2206340c289c0fcafa37430fb1e4644753f300446f22a22f44a14510d7c373cd47f4e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f',
  accessList: [],
  hash: '0xbb4fed62d09fa508b757a67ee1786f7be86214d233653996a98ba7f2800f338c',
  v: 0,
  r: '0xbe9c5136bedc0f66a8263c22cb383d452368466a2398517013922722e3352484',
  s: '0x2be3ec6375fe2fc420da53c7ee97de4cf93fe60bb1143bef030c93c58cba66ed',
  from: '0x53e09Dd70E20a0b5CeaF2447484063dcCbE3f219',
  confirmations: 0,
  wait: [Function (anonymous)]
}

@zodahu
Copy link
Contributor

zodahu commented May 7, 2024

  • The txApprove.gasLimit is typically insufficient for a flash loan. Consider using Ethers.js’s estimateGas for a more accurate gas estimate.
  • Additionally, simulate the transaction using tools like Tenderly to ensure it is ready for execution. You can then share the simulation results with us for more effective debugging.
  • Also, note that the nonce is set to 100, but it appears that the nonce for 0x53e09Dd70E20a0b5CeaF2447484063dcCbE3f219 on Polygon is not as high.

@lucarducci
Copy link
Author

lucarducci commented May 7, 2024

  • Could you clarify hot to get the gasLimit with Ethers.js's estimateGas?

I see I can get it with provider.getGasPrice() or provider.getFeeData() but both don't works.
Then I tried with the contract.estimateGas but I miss some info, here what I tried:

  // Is this correct? I took it from the transactionRequest
  let protolinkContractAddress="0xDec80E988F4baF43be69c13711453013c212feA8"; 
  let contract = new ethers.Contract(protolinkContractAddress, ABIprotolink, provider);
  // here I miss the parameters to execute this function
  let estimategas = await contract.estimateGas.executeWithSignerFee();

If this is a standard procedure to get the gas limit it would be helpful to add this to the docs.

Schermata 2024-05-07 alle 08 46 07

@zodahu
Copy link
Contributor

zodahu commented May 7, 2024

This Tenderly simulation indicates that 0x53e09dd70e20a0b5ceaf2447484063dccbe3f219 has not yet approved USDC for its agent 0x6E544A364fb3412E25809aA882EfD5b5d5ea36D1 (calcAgent).

If you are unfamiliar with how the Uniswap off-chain permit2 sign works, I recommend using permit2Type: approve initially (see documentation). First, execute the two approvals obtained from await api.estimateRouterData(routerData, { permit2Type: 'approve'}) on-chain. Afterwards, use Ethers.js’s estimateGas to estimate the gas limit and verify whether the transaction reverts.

@zodahu
Copy link
Contributor

zodahu commented May 9, 2024

@lucarducci Is there anything else we can help you with? And feel free to join our Discord we're here and happy to help!

@Juniorduc44
Copy link

So are flash loans working? Using furucombo I noticed it just fails the transactions.

Anyone know of alternative that works or have code that can be forked?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants