9

Can anyone help me?

I created a basic contract.But don't know the withdrawal function.Please help me.Thanks everyone I tried creating a basic function but it doesn't work

function withdraw() public {
    msg.sender.transfer(address(this).balance);
}
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
learn code
  • 91
  • 1
  • 1
  • 3

4 Answers4

20
payable(msg.sender).transfer(address(this).balance);

This line withdraws the native balance (ETH if your contract is on Ethereum network).


To withdraw a token balance, you need to execute the transfer() function on the token contract. So in order to withdraw all tokens, you need to execute the transfer() function on all token contracts.

You can create a function that withdraws any ERC-20 token based on the token contract address that you pass as an input.

pragma solidity ^0.8;

interface IERC20 {
    function transfer(address _to, uint256 _amount) external returns (bool);
}

contract MyContract {
    function withdrawToken(address _tokenContract, uint256 _amount) external {
        IERC20 tokenContract = IERC20(_tokenContract);
        
        // transfer the token from address of this contract
        // to address of the user (executing the withdrawToken() function)
        tokenContract.transfer(msg.sender, _amount);
    }
}

Mind that this code is unsafe - anyone can execute the withdrawToken() funciton. If you want to run it in production, add some form of authentication, for example the Ownable pattern.

Unfortunately, because of how token standards (and the Ethereum network in general) are designed, there's no easy way to transfer "all tokens at once", because there's no easy way to get the "non-zero token balance of an address". What you see in the blockchain explorers (e.g. that an address holds tokens X, Y, and Z) is a result of an aggregation that is not possible to perform on-chain.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • I use solidity ^0.5.0; and it shows error contracts/1.sol:94:9: DeclarationError: Identifier not found or not unique. IERC20 tokenContract = IERC20(_tokenContract); ^----^ – learn code Jul 27 '21 at 14:27
  • @learncode You probably forgot to define the interface in your code. I'm getting the same error only if I omit the interface definition. – Petr Hejda Jul 27 '21 at 14:28
  • I have compiled successfully but i got 1 new error This is :Gas estimation failed you can help me ? https://goerli.etherscan.io/tx/0x6a32cce4c67919ecc076e8d4cbad42721bb9753f873702846b84d8859f0a35d9 – learn code Jul 27 '21 at 14:39
  • pls help me @petr hejda – learn code Jul 27 '21 at 15:55
  • @learncode The linked tx is trying to withdraw `20000` (excl. decimals) of [WTH](https://goerli.etherscan.io/token/0xd1a30814590f49ce64ee9954fc776cdcb80f9612) token from the contract [0xd1a3081...](https://goerli.etherscan.io/address/0xd1a30814590f49ce64ee9954fc776cdcb80f9612), but this contract doesn't hold any of the WTH tokens. So it fails on trying to transfer tokens that your contract doesn't have. – Petr Hejda Jul 27 '21 at 20:53
  • I want to write a function to withdraw eth from a contract can you help me write eth withdrawal function ? help me please – learn code Jul 28 '21 at 04:06
  • @learncode In that case, what version of Solidity are you using and what error are you getting? Please update your original question with this information so it's clear that you want to transfer the native currency of the chain, and not an (ERC-20 or similar) token. – Petr Hejda Jul 28 '21 at 09:44
  • 1
    Does this mean I can use `payable(msg.sender).transfer(address(this).balance);` to transfer native token inside non-native token contract? Thus I can use such function to transfer locked up native token (for some reasons) in a non-native contract, and use `IERC20`'s `transfer` function to transfer non-native token? – haxpor Feb 16 '22 at 07:43
  • 1
    @haxpor Exactly. – Petr Hejda Feb 16 '22 at 08:03
3

Assuming your contract is ERC20, The transfer function defined in EIP 20 says:

Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The function SHOULD throw if the message caller’s account balance does not have enough tokens to spend.

Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.

function transfer(address _to, uint256 _value) public returns (bool success)

When you're calling an implementation of transfer, you're basically updating the balances of the caller and the recipient. Their balances usually are kept in a mapping/lookup table data structure.

See ConsenSys's implementation of transfer.

ƛƛƛ
  • 892
  • 7
  • 11
  • How to withdraw basic tokens like eth and bnb from a smart contract ? I have tried many times with no success Can you help me ? – learn code Jul 27 '21 at 16:24
  • pls give me a function – learn code Jul 27 '21 at 16:25
  • This is my contract:https://goerli.etherscan.io/address/0x2196cbcc5200ea6d9984fcc425dacc83932e3cf9#code – learn code Jul 27 '21 at 16:32
  • if you want to transfer "HRS" to another account, just call the `transfer` function https://goerli.etherscan.io/address/0x2196cbcc5200ea6d9984fcc425dacc83932e3cf9#writeContract – ƛƛƛ Jul 27 '21 at 16:52
  • if you want to transfer "ETH" or "USDT" to another account , how do i need to do it ? – learn code Jul 27 '21 at 16:56
  • if u want to transfer ETH from your contract to another address, first your contract has to have enough ETH to transfer out. Then you can invoke the `transfer` function on the recipient – ƛƛƛ Jul 27 '21 at 17:55
  • Can you say more about this I used the transfer function but it only transfers WTH tokens, not ETH can you help me write eth withdrawal function? – learn code Jul 28 '21 at 04:04
2

I came here to find a solution to allow the owner to withdraw any token which accidentally can be sent to the address of my smart contract. I believe it can be useful for others:

 /**
 * @dev transfer the token from the address of this contract  
 * to address of the owner 
 */
function withdrawToken(address _tokenContract, uint256 _amount) external onlyOwner {
    IERC20 tokenContract = IERC20(_tokenContract);

    // needs to execute `approve()` on the token contract to allow itself the transfer
    tokenContract.approve(address(this), _amount);

    tokenContract.transferFrom(address(this), owner(), _amount);
}
Maxim Vasilkov
  • 71
  • 1
  • 1
  • 8
1
  • Since it is a basic contract, I assume it is not erc20 token and if you just want to withdraw money:

    function withdraw(uint amount) external onlyOwner{
       (bool success,)=owner.call{value:amount}("");
       require(success, "Transfer failed!");
     }
    

This function should be only called by the owner.

  • If you want to withdraw entire balance during emergency situation:

    function emergencyWithdrawAll() external onlyWhenStopped onlyOwner {
       (bool success,)=owner.call{value:address(this).balance}("");
       require(success,"Transfer failed!");
     }
    

this function have two modifier: onlyWhenStopped onlyOwner

Use the Emergency Stop pattern when

  • you want to have the ability to pause your contract.
  • you want to guard critical functionality against the abuse of undiscovered bugs.
  • you want to prepare your contract for potential failures.

Modifiers:

modifier onlyOwner() {
    // owner is storage variable is set during constructor
    if (msg.sender != owner) {
      revert OnlyOwner();
    }
    _;
  }
  • for onlyWhenStopped we set a state variable:

      bool public isStopped=false; 
    

then the modifier

modifier onlyWhenStopped{
    require(isStopped);
    _;
  }
Yilmaz
  • 35,338
  • 10
  • 157
  • 202