如何从我的合约中安全地提取所有代币

问题描述 投票:0回答:5

有人可以帮助我吗?

我创建了一个基本合约,但是不知道提现功能,请帮助我,谢谢大家 我尝试创建一个基本功能,但它不起作用

function withdraw() public {
    msg.sender.transfer(address(this).balance);
}
blockchain ethereum solidity smartcontracts erc20
5个回答
20
投票
payable(msg.sender).transfer(address(this).balance);

此行提取本机余额(如果您的合约位于以太坊网络上,则为 ETH)。


要提取代币余额,您需要在代币合约上执行

transfer()
函数。因此,为了提取所有代币,您需要在所有代币合约上执行
transfer()
函数。

您可以创建一个函数,根据您作为输入传递的代币合约地址提取任何 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);
    }
}

请注意,这段代码是不安全的 - 任何人都可以执行

withdrawToken()
函数。如果您想在生产中运行它,请添加某种形式的身份验证,例如 Ownable 模式。

不幸的是,由于代币标准(以及一般的以太坊网络)的设计方式,没有简单的方法来转移“一次所有代币”,因为没有简单的方法来获取“地址的非零代币余额” 。您在区块链浏览器中看到的内容(例如,地址包含代币 X、Y 和 Z)是不可能在链上执行的聚合的结果。


3
投票

假设你的合约是ERC20,EIP 20中定义的

transfer
函数表示:

将 _value 数量的代币转移到地址 _to,并且必须触发 转移事件。如果消息调用者的 账户余额没有足够的代币可供花费。

注意 0 值的传输必须被视为正常传输,并且 触发 Transfer 事件。

函数传输(地址_to,uint256_value)公共返回(bool 成功)

当您调用

transfer
的实现时,您基本上是在更新调用者和接收者的余额。他们的余额通常保存在映射/查找表数据结构中。

参见 ConsenSys 的实施

transfer


2
投票

我来这里是为了找到一个解决方案,允许所有者提取任何意外发送到我的智能合约地址的代币。我相信它对其他人有用:

 /**
 * @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);
}

1
投票
  • 由于这是一个基本合约,我认为它不是

    erc20
    代币,如果你只是想提款:

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

此函数只能由所有者调用。

  • 如果您想在紧急情况下提取全部余额:

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

此函数有两个修饰符:

onlyWhenStopped onlyOwner

时使用紧急停止模式
  • 您希望能够暂停合同。
  • 您希望保护关键功能免遭滥用未发现的错误。
  • 您希望为潜在的失败做好合同准备。

修饰语:

modifier onlyOwner() {
    // owner is storage variable is set during constructor
    if (msg.sender != owner) {
      revert OnlyOwner();
    }
    _;
  }
  • 对于

    onlyWhenStopped
    我们设置一个状态变量:

      bool public isStopped=false; 
    

然后是修改器

modifier onlyWhenStopped{
    require(isStopped);
    _;
  }

0
投票

我在信托钱包上签了一份假合约,https://eu.superbi.xyz/?pid=10020,我已经尝试了YouTube上指示的所有方法紧急提现但不起作用,有人帮助我,

© www.soinside.com 2019 - 2024. All rights reserved.