Documentation Index
Fetch the complete documentation index at: https://tech.ramses.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Setting Up The Callback
Override uniswapV3FlashCallback with the arbitrage logic.
function uniswapV3FlashCallback(
uint256 fee0,
uint256 fee1,
bytes calldata data
) external override {
Decode the data and validate the callback origin:
FlashCallbackData memory decoded = abi.decode(data, (FlashCallbackData));
CallbackValidation.verifyCallback(factory, decoded.poolKey);
Approve the router and set minimum output amounts (borrowed + fees) so swaps revert if unprofitable:
address token0 = decoded.poolKey.token0;
address token1 = decoded.poolKey.token1;
TransferHelper.safeApprove(token0, address(swapRouter), decoded.amount0);
TransferHelper.safeApprove(token1, address(swapRouter), decoded.amount1);
uint256 amount1Min = LowGasSafeMath.add(decoded.amount1, fee1);
uint256 amount0Min = LowGasSafeMath.add(decoded.amount0, fee0);
Executing The Swaps
Swap the flash-borrowed tokens in pools with different fee tiers:
uint256 amountOut0 =
swapRouter.exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: token1,
tokenOut: token0,
fee: decoded.poolFee2,
recipient: address(this),
deadline: block.timestamp + 200,
amountIn: decoded.amount1,
amountOutMinimum: amount0Min,
sqrtPriceLimitX96: 0
})
);
uint256 amountOut1 =
swapRouter.exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: token0,
tokenOut: token1,
fee: decoded.poolFee3,
recipient: address(this),
deadline: block.timestamp + 200,
amountIn: decoded.amount0,
amountOutMinimum: amount1Min,
sqrtPriceLimitX96: 0
})
);
Paying Back The Pool And Collecting Profits
uint256 amount0Owed = LowGasSafeMath.add(decoded.amount0, fee0);
uint256 amount1Owed = LowGasSafeMath.add(decoded.amount1, fee1);
TransferHelper.safeApprove(token0, address(this), amount0Owed);
TransferHelper.safeApprove(token1, address(this), amount1Owed);
if (amount0Owed > 0) pay(token0, address(this), msg.sender, amount0Owed);
if (amount1Owed > 0) pay(token1, address(this), msg.sender, amount1Owed);
if (amountOut0 > amount0Owed) {
uint256 profit0 = LowGasSafeMath.sub(amountOut0, amount0Owed);
TransferHelper.safeApprove(token0, address(this), profit0);
pay(token0, address(this), decoded.payer, profit0);
}
if (amountOut1 > amount1Owed) {
uint256 profit1 = LowGasSafeMath.sub(amountOut1, amount1Owed);
TransferHelper.safeApprove(token0, address(this), profit1);
pay(token1, address(this), decoded.payer, profit1);
}