I have been playing with Uniswap v3 flashloand and testing it on mainnet fork. Experienced some wired behavior that needed your help to understand. Here is the code snippt for the Uniswap V3 flashloan callback which prints logs for debugging:
function uniswapV3FlashCallback(
uint256 fee0,
uint256 fee1,
bytes calldata data
) external {
require(msg.sender == address(pool), "not authorized");
FlashCallbackData memory decoded = abi.decode(
data,
(FlashCallbackData)
);
console.log("Balance of token1 on contract(before paying off loan):");
console.log(token1.balanceOf(address(this)));
console.log("Balance of token1 on pool(before paying off loan):");
console.log(token1.balanceOf(address(pool)));
// Repay borrow
if (fee0 > 0) {
token0.transferFrom(decoded.caller, address(this), fee0);
token0.transfer(address(pool), decoded.amount0 + fee0);
}
if (fee1 > 0) {
//Paying off the loan (back to the pool) with fee
token1.transfer(address(pool), decoded.amount1 + fee1);
console.log("Balance of token1 on contract (after paying off loan):");
console.log(token1.balanceOf(address(this)));
console.log("Balance of token1 on pool (after paying off loan):");
console.log(token1.balanceOf(address(pool)));
}
// console.log("Fee0:");
// console.log(fee0);//0
console.log("Fee1:");
console.log(fee1);
}
On mainnet fork, I impersonated as a USDC whale and funded 10 USDC to my contract, verifed with unit test. When I try borrow 5 USDC with 0.3% fee (1,500), I got an exception as below
Error: VM Exception while processing transaction: reverted with reason string 'F1'
After checking official doc, above error code F1 can be interpreted:
The balance of token1 in the given pool before the flash transaction must be less than, or equal to, the balance of token1 after the flash plus the fee
From the the printed the logs, I found a few issues I cannot understand. Please find my comments inline below:
UniswapV3Arb
UniswapV3MultiHopSwap
USDC balance of whale: 170961318210457n
Impersonation Started.
Impersonation completed.
✔ ensures contract is funded
USDC balance of whale: 170961308210457n
Impersonation Started.
Impersonation completed.
Current balance of USDC on contract = 10000000 USDC (decimals 6)
//Funded 10 USDC on my flashloan contract
Balance of token1 on contract(before paying off loan):
10000000
//Still remains as 10 USDC (decimals 6)
Balance of token1 on pool(before paying off loan):
29432076632681
Balance of token1 on contract (after paying off loan):
4985000 (This seems to be whats left after deducting 1,500 fee from borrowed 5 USDC. Where has my initial fund 10 USDC gone?)
Balance of token1 on pool (after paying off loan):
29432081647681 (Shouldn't it be larger? as The original value + 1,500. Thats why I received the Exception above?)
Fee1:
15000
Observed after paying off the loan:
- the balance becomes 4985000 (borrowedAmt - fee) than 9998500 (init fund - fee)
- Balance of USDC on pool still remains the same than getting 1,500 (fee) more
Am I doing anything wrong? Apprecite your advice.
1)Review and Adjust Repayment Logic: Make sure you’re only transferring the borrowed amount plus the fee back to the pool, and not inadvertently using the contract’s initial funds. 2)Enhance Diagnostic Logging: Add more detailed logs before and after each significant step to capture exact balance changes. This will help identify where balances are not changing as expected. 3)Verify Calculations: Ensure your fee and repayment calculations are accurate according to the flash loan’s terms. Correctly handling these calculations is crucial for avoiding the F1 error.
By focusing on these aspects, you should be good to go