如何通过另一个智能合约与已部署的 ERC20 代币进行交互?

Abi*_*yal 1 ethereum solidity erc20

我通过在 ERC20.sol 文件中实现 OpenZeppelin 创建了一个基本的 ERC20 令牌,如下所示:

pragma solidity ^0.6.4;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor(string memory _name, string memory _symbol)
        public
        ERC20(_name, _symbol)
    {
        _mint(msg.sender, 10000000000000000000000000000);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后实现另一个合约Contract.sol,如下:

import "./ERC20.sol";

pragma solidity ^0.6.4;

contract SimpleBank{
    Token tokenContract;

    constructor(Token _tokenContract) public {
        tokenContract = _tokenContract;
    }
    
    function deposit(uint amt) public returns (bool)  {
        require(amt != 0 , "deposit amount cannot be zero");
        tokenContract.transfer(address(this),amt);
        return true;
    }
} 
Run Code Online (Sandbox Code Playgroud)

因为,我已经从地址0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2部署了两个合约,所以它持有 10000000000000000000000000000 个代币。

但是当我deposit从同一地址调用函数时,出现以下错误:

交易到 SimpleBank.deposit 时出错:虚拟机错误:恢复。revert 事务已恢复到初始状态。合约给出的原因:“ERC20:转账金额超过余额”。调试事务以获取更多信息。



deploy那么,与已部署的 ERC20 代币交互以使该功能正常运行的正确方法是什么?

Pet*_*jda 5

  1. 用户地址0xAb8483...发送一个执行SimpleBank函数的交易deposit(),这使得in0xAb8483...的值。msg.senderSimpleBank

  2. 然后SimpleBank发送一个内部事务来执行Token函数transfer()。这使得SimpleBank地址(而不是0xAb8483...msg.sender成为in的值Token

    因此 SimpleBank 中的代码片段tokenContract.transfer(address(this),amt);正在尝试发送 的SimpleBank代币。不是用户的 ( 0xAb8483...) 令牌。

此代币转移(从第 2 点开始)会恢复,因为 SimpleBank 不拥有任何代币。这使得顶级事务(从第 1 点开始)也会恢复。


如果您希望SimpleBank能够转移 的0xAb8483...代币,0xAb8483...则需要approve()先将代币花掉SimpleBank。直接来自他们的地址,以便他们在合同msg.senderToken

然后SimpleBank才能执行transferFrom(0xAb8483..., address(this), amt)(from、to、amount)。


TLDR:你的合约不能花费它不拥有的代币,除非所有者手动批准你的合约花费它们。

如果它可以在未经批准的情况下花费别人的代币,那么就很容易从那些无法/不验证您的源代码的人那里窃取(通过花费他们的 USDT、WETH 和其他广泛使用的代币)。