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

How to interact with the deployed ERC20 token with another smart-contract?

我通过在 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);
    }
}

然后执行另一个合约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;
    }
} 

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

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

transact to SimpleBank.deposit errored: VM error: revert. revert The transaction has been reverted to the initial state. Reason provided by the contract: "ERC20: transfer amount exceeds balance". Debug the transaction to get more information.



那么,与已部署的 ERC20 令牌进行交互的正确方法是什么,以便 deploy 功能起作用。

  1. 用户地址0xAb8483...发送交易执行SimpleBank的函数deposit(),使得0xAb8483...成为msg.sender的值] 在 SimpleBank.

  2. 但是随后 SimpleBank 发送一个内部事务执行 Token 的函数 transfer()。这使得 SimpleBank 地址(不是 0xAb8483... 成为 Token.

    msg.sender 的值

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

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


如果您希望SimpleBank能够转移0xAb8483...的代币,0xAb8483...需要approve()代币首先被[=11=花费].直接来自他们的地址,因此他们在 Token 合同中是 msg.sender

只有SimpleBank才能执行transferFrom(0xAb8483..., address(this), amt)(from,to,amount)


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

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