简体   繁体   English

如何可靠地从我的合约中提取所有代币

[英]how to withdraw all tokens from the my contract in solidity

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。请帮助我。谢谢大家 我尝试创建一个基本 function 但它不起作用

function withdraw() public {
    msg.sender.transfer(address(this).balance);
}
msg.sender.transfer(address(this).balance);

This line withdraws the native balance (ETH if your contract is on Ethereum network).此行提取本机余额(如果您的合约在以太坊网络上,则为 ETH)。


To withdraw a token balance, you need to execute the transfer() function on the token contract.要提取代币余额,您需要对代币合约执行transfer()函数。 So in order to withdraw all tokens, you need to execute the transfer() function on all token contracts.因此,为了提取所有代币,您需要对所有代币合约执行transfer()函数。

You can create a function that withdraws any ERC-20 token based on the token contract address that you pass as an input.您可以创建一个函数,根据您作为输入传递的代币合约地址提取任何 ERC-20 代币。

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.请注意,这段代码是不安全的——任何人都可以执行withdrawToken()函数。 If you want to run it in production, add some form of authentication, for example the Ownable pattern.如果要在生产中运行它,请添加某种形式的身份验证,例如Ownable模式。

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 (eg that an address holds tokens X, Y, and Z) is a result of an aggregation that is not possible to perform on-chain.您在区块链浏览器中看到的(例如,一个地址持有代币 X、Y 和 Z)是无法在链上执行的聚合的结果。

Assuming your contract is ERC20, The transfer function defined in EIP 20 says:假设你的合约是 ERC20,EIP 20 中定义的transfer函数表示:

Transfers _value amount of tokens to address _to, and MUST fire the Transfer event.将 _value 数量的代币转移到地址 _to,并且必须触发 Transfer 事件。 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.注意 0 值的传输必须被视为正常传输并触发 Transfer 事件。

function transfer(address _to, uint256 _value) public returns (bool success)函数传输(地址 _to,uint256 _value)公开返回(布尔成功)

When you're calling an implementation of transfer , you're basically updating the balances of the caller and the recipient.当您调用transfer的实现时,您基本上是在更新调用者和接收者的余额。 Their balances usually are kept in a mapping/lookup table data structure.它们的余额通常保存在映射/查找表数据结构中。

See ConsenSys's implementation of transfer .请参阅ConsenSys 的transfer实现

  • Since it is a basic contract, I assume it is not erc20 token and if you just want to withdraw money:由于它是一个基本合约,我认为它不是erc20币,如果你只是想提款:

     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.此 function 只能由所有者调用。

  • 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这个 function 有两个修饰符: 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:对于onlyWhenStopped ,我们设置了一个 state 变量:

     bool public isStopped=false;

then the modifier然后修饰符

modifier onlyWhenStopped{
    require(isStopped);
    _;
  }

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

I am facing the same problem but my contract is deployed how can I upgrade my contract with the withdrawal function.我面临同样的问题,但我的合同已部署,如何使用提款功能升级我的合同。

Please help请帮忙

Thanking in anticipation期待中的感谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM