I have a very big contract that does some swaps and the profit of them is send to the contract's balance. I wanted to send the profit to my address with this function (I'm using Remix IDE to test it):
function withdraw() public {
require(msg.sender == owner, "only owner can do this");
(bool status,) = owner.call{value: address(this).balance}("");
require(status == true, "error during transaction");
console.log("after withdraw", IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2).balanceOf(address(this)));
}
the final console.log shows that not all the balance has been sent to the owner. I had some questions: is this the right method to send the contract balance to an address?, Why it isn't sending the entire balance to the owner address?, When i do address(this).balance
it returns 0 but when i do IERC20(tokens[0]).balanceOf(address(this))
it returns a very high number, why is that?
Note that my contract doesnt have a fallback or receive function.
Full contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "hardhat/console.sol";
contract Arbitrage is DyDxFlashLoan {
IUniswapV2Router02 public immutable uRouter;
IUniswapV2Router02 public immutable sRouter;
address public owner;
constructor(address _uRouter, address _sRouter) {
uRouter = IUniswapV2Router02(_uRouter);
sRouter = IUniswapV2Router02(_sRouter);
owner = msg.sender;
}
function executeTrade(
address _tokenA,
address _tokenB,
uint256 _flashAmount,
bool _startOnUniswap
) external {
uint balanceBefore = IERC20(_tokenA).balanceOf(address(this));
bytes memory data = abi.encode(
_startOnUniswap,
_tokenA,
_tokenB,
_flashAmount,
balanceBefore
);
flashloan(_tokenA, _flashAmount, data);
}
function callFunction(
address,
Info calldata,
bytes calldata data
) external onlyPool {
(
bool _startOnUniswap,
address _tokenA,
address _tokenB,
uint256 flashAmount,
uint256 balanceBefore
) = abi.decode(data, (bool, address, address, uint256, uint256));
uint balanceAfter = IERC20(_tokenA).balanceOf(address(this));
require(
balanceAfter - balanceBefore == flashAmount,
"Didn't receive flash loan"
);
address[] memory tokens = new address[](2);
tokens[0] = _tokenA;
tokens[1] = _tokenB;
if (_startOnUniswap) {
swapOnUniswap(flashAmount, 0, tokens);
tokens[0] = _tokenB;
tokens[1] = _tokenA;
swapOnSushiswap(
IERC20(tokens[0]).balanceOf(address(this)),
10,
tokens
);
} else {
console.log("Ho 10 WETH e li swappo per x COMPOUND");
swapOnSushiswap(flashAmount, 0, tokens);
tokens[0] = _tokenB;
tokens[1] = _tokenA;
console.log("Ho x COMPOUND e li swappo per >10 WETH");
swapOnUniswap(
IERC20(tokens[0]).balanceOf(address(this)),
10,
tokens
);
}
}
function swapOnUniswap(
uint _amountIn,
uint _amountOut,
address[] memory _path
) internal {
require(
IERC20(_path[0]).approve(address(uRouter), _amountIn),
"Uniswap failed the approval"
);
uint[] memory amounts = uRouter.swapExactTokensForTokens(
_amountIn,
_amountOut,
_path,
address(this),
(block.timestamp + 1200)
);
console.log(
"UNISWAP: Input tokens (COMP):",
amounts[0],
"Output tokens (ETH):",
amounts[1]
);
}
function swapOnSushiswap(
uint _amountIn,
uint _amountOut,
address[] memory _path
) internal {
require(
IERC20(_path[0]).approve(address(sRouter), _amountIn),
"Sushiswap failed the approval"
);
uint[] memory amounts = sRouter.swapExactTokensForTokens(
_amountIn,
_amountOut,
_path,
address(this),
(block.timestamp + 1200)
);
console.log(
"SUSHISWAP: Input tokens (ETH):",
amounts[0],
"Output tokens (COMP):",
amounts[1]
);
}
function withdraw() public {
require(msg.sender == owner, "Only the owner can cashout");
(bool success, ) = owner.call{value: address(this).balance}("");
require(success == true, "error");
}
}