Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to withdraw from the smart contract to the wallet #25

Open
enricocagliari opened this issue Feb 13, 2022 · 12 comments
Open

How to withdraw from the smart contract to the wallet #25

enricocagliari opened this issue Feb 13, 2022 · 12 comments

Comments

@enricocagliari
Copy link

Hi Everyone,

I managed to deploy the smart contract and perform the flash loans. However, I don't know how to withdraw the funds from the smart contract.
Let's talk with the case on hand:

To do the flashloan, funds are transferred from wallet to the contract with transaction https://kovan.etherscan.io/tx/0x9c3d95bd9ddb14e7debfe9153724f7b3aaf0d981b4657d1a000e2d70860eff44 to cover the fees. Then I'm able to execute the flashloan correctly.

However, now the contract has a balance, that should be transferred back to my wallet. So my doubt is:

  • How do I transfer the balance on the contract back to my wallet?
  • Could be that the code is effectively transferring the profit back to the wallet, but I am not seeing it because there is no profit in the transaction I did? It was only the flashloan, so there is a loss for the fees.

Thanks for who can clarify me this.

@ch1ch0gz
Copy link

Hi,

FlashloanV2 is Withdrawable hence you can use the function withdraw.

Something like the below would withdraw all the weth you have in your flashloan for instance.

image

@enricocagliari
Copy link
Author

Thank you @ch1ch0gz for your solution, at least this is a step forward.

Even though, when I run it, I get an error. Here is the response after running "brownie run scripts/withdraw_function.py --network kovan":


`Brownie v1.17.2 - Python development framework for Ethereum

AaveFlashloanMixFunzionaYesmodificareCopyProject is the active project.

Running 'scripts/withdraw_function.py::main'...
Getting flashloan contract...
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/_cli/run.py", line 51, in main
return_value, frame = run(
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/project/scripts.py", line 103, in run
return_value = f_locals[method_name](*args, **kwargs)
File "./scripts/withdraw_function.py", line 14, in main
tx = flashloan.Withdraw(weth, {"from": acct})
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/network/contract.py", line 763, in getattribute
raise AttributeError(f"Contract '{self._name}' object has no attribute '{name}'")
AttributeError: Contract 'FlashloanV2' object has no attribute 'Withdraw'`


Can you tell me what am I missing?

@ch1ch0gz
Copy link

ch1ch0gz commented Apr 2, 2022

Has your flashLoan contract got "contract FlashloanV2 is FlashLoanReceiverBaseV2, Withdrawable " withdrawable inherit?
image

@enricocagliari
Copy link
Author

I think you are right, I do not have that line in any file, and I expecially paid attention at contract.py, and I do not have that line.
Can you provide the whole function, so I can add it there and see how it turns out to work?

@ch1ch0gz
Copy link

ch1ch0gz commented Apr 4, 2022

i think you are missing adding the import Withdrawable on FlashLoanReceiverBaseV2.sol


// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;

import { SafeMath } from '@openzeppelin/contracts/math/SafeMath.sol';
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import { IFlashLoanReceiverV2 } from './../../../interfaces/v2/IFlashLoanReceiverV2.sol';
import { ILendingPoolAddressesProviderV2 } from './../../../interfaces/v2/ILendingPoolAddressesProviderV2.sol';
import { ILendingPoolV2 } from './../../../interfaces/v2/ILendingPoolV2.sol';
import "../../utils/Withdrawable.sol";

/** 
    !!!
    Never keep funds permanently on your FlashLoanReceiverBase contract as they could be 
    exposed to a 'griefing' attack, where the stored funds are used by an attacker.
    !!!
 */
abstract contract FlashLoanReceiverBaseV2 is IFlashLoanReceiverV2 {
  using SafeERC20 for IERC20;
  using SafeMath for uint256;

  ILendingPoolAddressesProviderV2 public immutable override ADDRESSES_PROVIDER;
  ILendingPoolV2 public immutable override LENDING_POOL;

  constructor(address provider) public {
    ADDRESSES_PROVIDER = ILendingPoolAddressesProviderV2(provider);
    LENDING_POOL = ILendingPoolV2(ILendingPoolAddressesProviderV2(provider).getLendingPool());
  }

  receive() payable external {}
}

And the Withdrawable.sol looks like


pragma solidity ^0.6.6;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
    Ensures that any contract that inherits from this contract is able to
    withdraw funds that are accidentally received or stuck.
 */
 
contract Withdrawable is Ownable {
    using SafeERC20 for ERC20;
    address constant ETHER = address(0);

    event LogWithdraw(
        address indexed _from,
        address indexed _assetAddress,
        uint amount
    );

    /**
     * @dev Withdraw asset.
     * @param _assetAddress Asset to be withdrawn.
     */
    function withdraw(address _assetAddress) public onlyOwner {
        uint assetBalance;
        if (_assetAddress == ETHER) {
            address self = address(this); // workaround for a possible solidity bug
            assetBalance = self.balance;
            msg.sender.transfer(assetBalance);
        } else {
            assetBalance = ERC20(_assetAddress).balanceOf(address(this));
            ERC20(_assetAddress).safeTransfer(msg.sender, assetBalance);
        }
        emit LogWithdraw(msg.sender, _assetAddress, assetBalance);
    }
} 

@ch1ch0gz
Copy link

ch1ch0gz commented Apr 4, 2022

Has your flashLoan contract got "contract FlashloanV2 is FlashLoanReceiverBaseV2, Withdrawable " withdrawable inherit? image

Here I was talking about Flashloan.sol which is another file you need to modify.

@enricocagliari
Copy link
Author

enricocagliari commented Apr 10, 2022

@ch1ch0gz your advices here are outstanding. Me and probably all the people reading this thread owe you a big thank you.
Please check your email, I sent you something via GitHub :) .

Now, I was messing around with the code, I did not solve this mystery, but I have some error logs I want you to take a look at.

  • First, I compared Withdrawable.sol and FlashLoanReceiverBaseV2.sol with the code you provided, and I can confirm I have the exact same code.
  • Based on your response of March 16 2022, I created the file "withdraw_function.py" which has the following code:

---Code Begins---

from brownie import FlashloanV2, accounts, config, network, interface

def main():
"""
Withdraw Tokens from flashloanW
"""

acct = accounts.add(
    config["wallets"]["from_key"]
)
print("Getting flashloan contract...")
flashloan = FlashloanV2[len(FlashloanV2) - 1]
weth = interface.WethInterface(config["networks"][network.show_active()]["weth"])
tx = flashloan.Withdraw(weth, {"from": acct})
return flashloan

---Code Ends---

  • I do not see a file Flashloan.sol, but I have FlashloanV2.sol, I guess this is the file you are referring to, right?

In my file I have the line "contract FlashloanV2 is FlashLoanReceiverBaseV2, Withdrawable" exactly as wrote by @PatrickAlphaC in https://github.com/brownie-mix/aave-flashloan-mix/blob/master/contracts/v2/FlashloanV2.sol

If I run "brownie run scripts/withdraw_function.py --network kovan" having the line "contract FlashloanV2 is FlashLoanReceiverBaseV2, Withdrawable" in FlashloanV2.sol I get:

---Code Begins---

Brownie v1.17.2 - Python development framework for Ethereum

Compiling contracts...
Solc version: 0.6.12
Optimizer: Enabled Runs: 200
EVM Version: Istanbul
Generating build data...

AaveFlashloanMixFunzionaYesmodificareCopyProject is the active project.

Running 'scripts/withdraw_function.py::main'...
Getting flashloan contract...
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/_cli/run.py", line 51, in main
return_value, frame = run(
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/project/scripts.py", line 103, in run
return_value = f_locals[method_name](*args, **kwargs)
File "./scripts/withdraw_function.py", line 12, in main
flashloan = FlashloanV2[len(FlashloanV2) - 1]
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/network/contract.py", line 174, in getitem
return self._contracts[i]
IndexError: list index out of range

---Code Ends---

Now, if I run "brownie run scripts/withdraw_function.py --network kovan" having the line you suggested "contract FlashloanV2_aave is FlashLoanReceiverBaseV2, Withdrawable" in FlashloanV2.sol I get:

---Code Begins---

Brownie v1.17.2 - Python development framework for Ethereum

Compiling contracts...
Solc version: 0.6.12
Optimizer: Enabled Runs: 200
EVM Version: Istanbul
Generating build data...

AaveFlashloanMixFunzionaYesmodificareCopyProject is the active project.
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/_cli/run.py", line 51, in main
return_value, frame = run(
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/project/scripts.py", line 53, in run
module = _import_from_path(script)
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/project/scripts.py", line 149, in _import_from_path
_import_cache[import_str] = importlib.import_module(import_str)
File "/usr/lib/python3.9/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen, line line, in in
File "<frozen, line line, in in
File "<frozen, line line, in in
File "<frozen, line line, in in
File "<frozen, line line, in in
File "<frozen, line line, in in
File "./scripts/withdraw_function.py", line 1, in
from brownie import FlashloanV2, accounts, config, network, interface
ImportError: cannot import name 'FlashloanV2' from 'brownie' (/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/init.py)

---Code Ends---

Said all that, still the withdrawal from the smart contract to the wallet does not get execute successfully. Suggestions?

@ch1ch0gz
Copy link

ch1ch0gz commented Apr 11, 2022

Can you quickly try having
image
in your FlashloanV2.sol contract instead of
image
Flashloan_aave is a different flashloan I am playing with.

@enricocagliari
Copy link
Author

The response is get is :

Brownie v1.17.2 - Python development framework for Ethereum

Compiling contracts...
Solc version: 0.6.12
Optimizer: Enabled Runs: 200
EVM Version: Istanbul
Generating build data...

OpenZeppelin/[email protected]/Context
OpenZeppelin/[email protected]/Ownable
OpenZeppelin/[email protected]/SafeMath
OpenZeppelin/[email protected]/ERC20
OpenZeppelin/[email protected]/IERC20
OpenZeppelin/[email protected]/SafeERC20
OpenZeppelin/[email protected]/Address
Withdrawable
FlashloanV2
FlashLoanReceiverBaseV2
IFlashLoanReceiverV2
ILendingPoolAddressesProviderV2
ILendingPoolV2
DataTypes

Running 'scripts/withdraw_function.py::main'...
Getting flashloan contract...
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/_cli/run.py", line 51, in main
return_value, frame = run(
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/project/scripts.py", line 103, in run
return_value = f_locals[method_name](*args, **kwargs)
File "./scripts/withdraw_function.py", line 12, in main
flashloan = FlashloanV2[len(FlashloanV2) - 1]
File "/usr/local/lib/python3.9/dist-packages/eth_brownie-1.17.2-py3.9.egg/brownie/network/contract.py", line 174, in getitem
return self._contracts[i]
IndexError: list index out of range

@Abdel364
Copy link

@ch1ch0gz thank you i solved it with your guide i want to send you an email to say thank you but i didn't find your email

@Allegoryof
Copy link

@ch1ch0gz Hello i just sent you a message on twitter, i just saw this and i'd need your assistance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@enricocagliari @ch1ch0gz @Abdel364 @Allegoryof and others