Hello all,
I wrote a smart contract, that can borrow a flashloan on balancer, make trades and repay the loan. If I run it on hardhat it works just fine, but if I deploy to the mainnet, I cannot even estimate gas for calling the function. It fails every time. So this is my smart contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IFlashLoanRecipient.sol";
import "./IBalancerVault.sol";
import "./interfaces/IUniswapV2Router02.sol";
contract FlashLoanArbitrage {
address payable private owner;
address private vault;
address private sushiRouter;
address private quickRouter;
address private apeRouter;
address public matic = 0x0000000000000000000000000000000000001010;
constructor(
address _vault,
address _sushiRouter,
address _quickRouter,
address _apeRouter
) {
owner = payable(msg.sender);
sushiRouter = _sushiRouter;
quickRouter = _quickRouter;
apeRouter = _apeRouter;
vault = _vault;
}
event FlashLoanResult(
address indexed token,
uint256 amountBorrowed,
uint256 amountProfit,
uint256 timestamp
);
modifier onlyOwner() {
require(msg.sender == owner, "Only Owner can call this function!");
_;
}
receive() external payable {}
function withdraw(IERC20 token) private {
//If contract needs to be funded, then compare here, that everytime there is enough matic here
uint256 amount = 0;
require(address(token) != address(0), "Invalid token address");
if (matic == address(token)) {
amount = address(this).balance;
require(amount > 0, "Not enough MATIC token to Withdraw");
owner.transfer(amount);
} else {
amount = token.balanceOf(address(this));
require(amount > 0, "Not enough token to Withdraw");
token.transfer(owner, amount);
}
}
function withdrawOnlyOwner(address token) external payable onlyOwner {
uint256 amount = 0;
require(address(token) != address(0), "Invalid token address");
if (matic == token) {
amount = address(this).balance;
require(amount > 0, "Not enough MATIC token to WithdrawOnlyOwner");
payable(msg.sender).transfer(amount);
} else {
IERC20 token_transfer = IERC20(token);
amount = token_transfer.balanceOf(address(this));
require(amount > 0, "Not enough token to WithdrawOnlyOwner");
token_transfer.transfer(payable(msg.sender), amount);
}
}
function changeAddresses(
address _quickRouter,
address _sushiRouter,
address _apeRouter,
address _vault
) external onlyOwner {
sushiRouter = _sushiRouter;
quickRouter = _quickRouter;
apeRouter = _apeRouter;
vault = _vault;
}
function balance(address token_address) public view returns (uint256) {
uint256 Balance = IERC20(token_address).balanceOf(address(this));
return Balance;
}
function swapper(
address dex_router,
uint256 _amountIn,
uint256 _amountOutMin,
address _tokenIn,
address _tokenOut,
uint256 _deadline
) private returns (uint256) {
//Zum testen muss das womöglich auf public gesetzt werden
require(
IERC20(_tokenIn).approve(quickRouter, _amountIn),
"Approve for Swapping failed."
);
require(
_amountIn >= balance(_tokenIn),
"Error: Actual amount received is less than expected"
); // check if actual amount is less than expected
address[] memory path;
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
uint256 deadline = block.timestamp + _deadline;
uint256[] memory amounts = IUniswapV2Router02(dex_router)
.swapExactTokensForTokens(
_amountIn,
_amountOutMin,
path,
address(this),
deadline
);
require(amounts[1] > 0, "Output amount should be greater than 0");
return amounts[1];
}
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory data
) external {
address dexA;
address dexB;
address[] memory trade_tokens;
uint24 fees;
uint256[] memory outputs;
(dexA, dexB, trade_tokens, fees, outputs) = abi.decode(
data,
(address, address, address[], uint24, uint256[])
);
for (uint256 i = 0; i < tokens.length; ++i) {
IERC20 token = tokens[i];
uint256 amount = amounts[i] + feeAmounts[i];
uint256 amountOut0 = 0;
uint256 amountOut1 = 0;
amountOut0 = swapper(
dexA,
outputs[0],
outputs[1],
trade_tokens[0],
trade_tokens[1],
(block.timestamp + 3000)
);
amountOut1 = swapper(
dexB,
balance(trade_tokens[1]),
0,
trade_tokens[1],
trade_tokens[0],
(block.timestamp + 3000)
);
emit FlashLoanResult(
trade_tokens[0],
amounts[i],
balance(trade_tokens[1]),
(block.timestamp + 3000)
);
token.transfer(vault, amount);
withdraw(tokens[i]);
}
}
function flashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external onlyOwner {
IBalancerVault(vault).flashLoan(
IFlashLoanRecipient(address(this)),
tokens,
amounts,
userData
);
}
}
ant that is how I am estimating the gas I need:
require("dotenv").config();
const { ethers } = require("ethers");
const flashloanABI = require("./abis/flashloan_abi.json");
const abiCoder = ethers.utils.defaultAbiCoder;
const FLASHLOAN = process.env.CONTRACT_ADDRESS;
const POLYGON_MAINNET_QUICKNODE= process.env.POLYGON_MAINNET_QUICKNODE;
const provider = new ethers.providers.JsonRpcProvider(
POLYGON_MAINNET_QUICKNODE
);
const flash_contract = new ethers.Contract(FLASHLOAN, flashloanABI, provider);
async function estimateGas(amountIn_wei, tokenIn_address, data) {
console.log("We are calculating");
try {
const functionData = flash_contract.interface.encodeFunctionData(
"flashLoan",
[[tokenIn_address], [amountIn_wei], data]
);
const gasAmount = await provider.estimateGas({
from: "0x5C42F93937389e73A7317e2108cbcFdECf658002",
to: FLASHLOAN,
data: functionData,
});
console.log(`Estimated gas cost: ${gasAmount}`);
} catch (e) {
console.log(e);
}
console.log("Estimated gas limit:", gasEstimate.toString());
return gasLimit;
}
async function testingGas() {
const tokenIn = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";
const amountIn = ethers.utils.parseUnits("1", 18);
const data = abiCoder.encode(
["address", "address", "address[]", "uint24", "uint256[]"],
[
router_addr_quickswap,
router_addr_sushiswap,
[tokenIn, "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270"],
0,
[amountIn, 0, 0, 0, 0],
]
);
const gas = await estimateGas(amountIn, tokenIn, data);
}
testingGas();
The error is this:
Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="execution reverted: TransferHelper: TRANSFER_FROM_FAILED", method="estimateGas", transaction={"from":"0x5C42F93937389e73A7317e2108cbcFdECf658002","to":"0x1E82728A4900fA5D9CDB1BaC1202B1Ee9F0F14b2","data":"0x788fb484000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f61900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b4799750600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","accessList":null}, error={"reason":"processing response error","code":"SERVER_ERROR","body":"{\"jsonrpc\":\"2.0\",\"id\":49,\"error\":{\"code\":3,\"message\":\"execution reverted: TransferHelper: TRANSFER_FROM_FAILED\",\"data\":\"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000\"}}\n","error":{"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000"},"requestBody":"{\"method\":\"eth_estimateGas\",\"params\":[{\"from\":\"0x5c42f93937389e73a7317e2108cbcfdecf658002\",\"to\":\"0x1e82728a4900fa5d9cdb1bac1202b1ee9f0f14b2\",\"data\":\"0x788fb484000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f61900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b4799750600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}],\"id\":49,\"jsonrpc\":\"2.0\"}","requestMethod":"POST","url":"https://skilled-sly-dream.matic.discover.quiknode.pro/fbd58ef38b15bc85d36db970daa194fb95a01a95/"}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.1)
at Logger.makeError (c:\Users\danis\arb_gpt\node_modules\@ethersproject\logger\lib\index.js:238:21)
at Logger.throwError (c:\Users\danis\arb_gpt\node_modules\@ethersproject\logger\lib\index.js:247:20)
at checkError (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:122:20)
at JsonRpcProvider.<anonymous> (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:751:47)
at step (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:48:23)
at Object.throw (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:29:53)
at rejected (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:21:65)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
reason: 'execution reverted: TransferHelper: TRANSFER_FROM_FAILED',
code: 'UNPREDICTABLE_GAS_LIMIT',
method: 'estimateGas',
transaction: {
from: '0x5C42F93937389e73A7317e2108cbcFdECf658002',
to: '0x1E82728A4900fA5D9CDB1BaC1202B1Ee9F0F14b2',
data: '0x788fb484000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f61900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b4799750600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
accessList: null
},
error: Error: processing response error (body="{\"jsonrpc\":\"2.0\",\"id\":49,\"error\":{\"code\":3,\"message\":\"execution reverted: TransferHelper: TRANSFER_FROM_FAILED\",\"data\":\"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000\"}}\n", error={"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000"}, requestBody="{\"method\":\"eth_estimateGas\",\"params\":[{\"from\":\"0x5c42f93937389e73a7317e2108cbcfdecf658002\",\"to\":\"0x1e82728a4900fa5d9cdb1bac1202b1ee9f0f14b2\",\"data\":\"0x788fb484000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f61900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b4799750600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}],\"id\":49,\"jsonrpc\":\"2.0\"}", requestMethod="POST", url="https://skilled-sly-dream.matic.discover.quiknode.pro/fbd58ef38b15bc85d36db970daa194fb95a01a95/", code=SERVER_ERROR, version=web/5.7.1)
at Logger.makeError (c:\Users\danis\arb_gpt\node_modules\@ethersproject\logger\lib\index.js:238:21)
at Logger.throwError (c:\Users\danis\arb_gpt\node_modules\@ethersproject\logger\lib\index.js:247:20)
at c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:313:32
at step (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:33:23)
at Object.next (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:14:53)
at fulfilled (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
reason: 'processing response error',
code: 'SERVER_ERROR',
body: '{"jsonrpc":"2.0","id":49,"error":{"code":3,"message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED","data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000"}}\n',
error: Error: execution reverted: TransferHelper: TRANSFER_FROM_FAILED
at getResult (c:\Users\danis\arb_gpt\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:191:21)
at processJsonFunc (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:356:22)
at c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:288:46
at step (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:33:23)
at Object.next (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:14:53)
at fulfilled (c:\Users\danis\arb_gpt\node_modules\@ethersproject\web\lib\index.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 3,
data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000'
},
requestBody: '{"method":"eth_estimateGas","params":[{"from":"0x5c42f93937389e73a7317e2108cbcfdecf658002","to":"0x1e82728a4900fa5d9cdb1bac1202b1ee9f0f14b2","data":"0x788fb484000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f61900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b4799750600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"id":49,"jsonrpc":"2.0"}',
requestMethod: 'POST',
url: 'https://skilled-sly-dream.matic.discover.quiknode.pro/fbd5.../'
}
}
I hope somebody can help me with this, I don't know what to do anymore...
Thank you!!!