0

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");
    }
}

1 Answer 1

1

What balance are you talking about ? If that's your ETH balance, then that's normal. What the first snippet does is that it first sends the whole balance in ETH of your contract. Then you are checking you WETH balance, which is a wrapped version of ETH but is absolutely not the same.

What you may want is to wrap your WETH and send them as an ERC20 token to your wallet, then the balance would be decreased accordingly.

6
  • How can i wrap my WETH and send them as ERC20 token?
    – Shadq
    Commented May 13, 2023 at 8:39
  • Like this? (bool success, ) = owner.call{value:ERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2).balanceOf(address(this))}("");
    – Shadq
    Commented May 13, 2023 at 9:21
  • Yes, this is one of the ways to wrap some ETH
    – Franfran
    Commented May 14, 2023 at 12:08
  • It reverts when i try it
    – Shadq
    Commented May 14, 2023 at 13:08
  • Oh sorry, as a value you should send your ETH balance address(this).balance
    – Franfran
    Commented May 14, 2023 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.