我如何通过另一个智能合约转移 ERC20 代币?

How can I transfer ERC20 token by another smart contract?

我设计了一个 erc20 代币和一个智能合约来转移该代币,但是当我触发转移功能时,remix 告诉我下图。

我做的是先部署代币智能合约,再部署DAO智能合约,然后调用creatSubDAO函数开始转账。

相关代码如下:

// SPDX-License-Identifier: GPL-3.0
 pragma solidity >=0.7.0 <0.9.0;


interface IERC20 {

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);

function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);


event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}

合约代币:

contract Dtoken is IERC20{

string public name = "DAO Token";
string public symbol = "D";
uint256 public totalSupply = 1000000000000000000000000;
uint8 public decimals = 18;

mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;

constructor() {
    balanceOf[msg.sender] = totalSupply;
}

function transfer(address _to, uint256 _value) public returns (bool success) {
    require(balanceOf[msg.sender] >= _value);
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
    return true;
}

function approve(address _spender, uint256 _value) public returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
}

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    require(_value <= balanceOf[_from]);
    require(_value <= allowance[_from][msg.sender]);
    balanceOf[_from] -= _value;
    balanceOf[_to] += _value;
    allowance[_from][msg.sender] -= _value;
    emit Transfer(_from, _to, _value);
    return true;
   }
 }

合约MasterDao:

import "./Dtoken.sol";

contract MasterDAO {

uint proposalNum;

mapping (address => Member) public members;
mapping (uint => Proposal) public proposals;
mapping (uint => SubDAO) public subDAOs;
// SubDAO[] public subDAOs;

function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
    SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
    daoAddress = address(subDAO);
}} 

SubDao 合约:

 contract SubDAO {

uint proposalNum;
address lender;
uint poolGap;
uint currentStake;
uint256 public DAOID;
MasterDAO master;
address stakeItem;
uint rate;
Dtoken public token;

mapping(address => Member) members;
mapping (uint => Proposal) public proposals;

string[] description;

event Transfrom(address, uint);

struct Member {
    address memberAddress;
    string nickName;
    bool alreadyExist;
}


struct Proposal {
    string description;
    address payable recipient;
    bool executed;
    uint proposalID;
    address[] agreeMembers;
    address[] disagreeMembers;
    bool exectuable;
    uint amount;
    Dtoken token;
}

modifier membership (MasterDAO masterDAO, address _staker){
    require(masterDAO.addressExist(_staker) == true);
    _;
}

modifier lenderLimit {
    require(msg.sender == lender);
    _;
}

modifier balanceLimit(uint amount) {
    require(amount <= poolGap - currentStake);
    _;
}

constructor (uint _poolGap, uint _DAOID, address _lender, uint _rate, MasterDAO caller, Dtoken _token) {
    currentStake = 0;
    poolGap = _poolGap;
    DAOID = _DAOID;
    lender = _lender;
    master = caller;
    rate = _rate;
    token = _token;
    token.transferFrom(address(this), address(this), 10);
}

我转移代币有没有做错什么?谢谢!

来自 SubDao 构造函数:

token.transferFrom(address(this), address(this), 10);

此代码段试图将令牌从刚刚创建的 SubDao 地址(第一个参数)转移到完全相同的地址(第二个参数)。

新创建的 SubDao 地址很可能一开始就没有任何要从转移的代币。


如果想将MasterDao中的token转移到新创建的SubDao中,可以将SubDao构造函数中的transferFrom()去掉,实现转移在 MasterDao 函数中 createSubDAO():

function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
    SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
    daoAddress = address(subDAO);

    // transfer 10 units of the `Dtoken`
    // from the `MasterDao` address
    // to the newly created `SubDao` address
    // assuming that `MasterDao` has sufficient token balance
    Dtoken(_token).transfer(daoAddress, 10);
}}