1

我的意图是让 ERC721 代币只能通过我的 ERC20 代币转移

传输流是

  1. 买方批准 ERC20 给卖方。
  2. 卖方将 ERC721 转让给买方。
  3. My ERC721 Token的转账功能先将ERC20从Buyer转账给Seller,再将ERC721从Seller转账给Buyer。

还原错误发生在 ERC20 传输步骤。

我尝试删除每一行以找到还原点。我发现了。

这是我的测试代码

const token20 = artifacts.require("MyToken20");
const token721 = artifacts.require("MyToken721");

contract("Test", async()=>{

//...

  // Buyer token20 approve to Seller
  it("Token20 approve", async()=>{
    var value = web3.toWei(token721Price, "ether");
    await contract20.approve(seller, value, {from:buyer});

    var allowed = await contract20.allowance(buyer, seller);
    allowed = web3.fromWei(allowed, "ether");
    assert.equal(allowed, token721Price);
  });

  // Seller transfer token721 to Buyer
  // token20 transfer to Seller inside of function transferMy721
  it("Token721 transfer", async()=>{
    var allowed = await contract20.allowance(buyer, seller);
    allowed = web3.fromWei(allowed, "ether");
    assert.equal(allowed, token721Price);

    await contract721.transferMy721(buyer, token721Id, {from:seller});  // <--- revert here

    var newOwner = await contract721.ownerOf(token721Id);
    assert.equal(newOwner, buyer);
  });

});

我的合同中的还原点在这里

contract MyToken721 is ERC721Token{                                                       
  string public name = "My ERC721 Token Product";                                         
  string public symbol = "MTP";                                                           

  mapping(uint256 => uint256) my721TokenPrice;                                            

  MyToken20 token;                                                                        

  constructor(MyToken20 _token) public ERC721Token(name, symbol){                         
    require(_token != address(0));                                                        
    token = _token;                                                                       
  }                                                                                       

  function mint(address _to, uint256 _tokenId, uint256 _price) public {                   
    _mint(_to, _tokenId);                                                                 
    my721TokenPrice[_tokenId] = _price;                                                   
  }                                                                                       

  function transferMy721(address _to, uint256 _tokenId) public returns(bool){             
    require(msg.sender == ownerOf(_tokenId));                                             

    uint256 tokenPrice = my721TokenPrice[_tokenId];                                       

    if( token.transferFrom(_to, msg.sender, tokenPrice) == false )  // <--- revert here   
      return false;                                                                       

    super.approve(_to, _tokenId);                                                         
    super.transferFrom(msg.sender, _to, _tokenId);                                        

    return true;                                                                          
  }                                                                                       
//...                                                                                                                                                                                
}      

ERC20 StandardToken 合约中的还原点在这里

contract StandardToken is ERC20, BasicToken {                                 

  mapping (address => mapping (address => uint256)) internal allowed;         

  function transferFrom(address _from, address _to, uint256 _value)                                                                           
    public returns (bool)
  {                                                                           
    require(_value <= balances[_from]);                                       
    require(_value <= allowed[_from][msg.sender]);  // <--- revert here       
    require(_to != address(0));                                               

    balances[_from] = balances[_from].sub(_value);                            
    balances[_to] = balances[_to].add(_value);                                
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);      
    emit Transfer(_from, _to, _value);                                        
    return true;                                                              
  }  
//...
}

如您所见,在我的测试代码中,我仔细检查了

allowed[_from][msg.sender]

请在这里查看我的完整代码

4

1 回答 1

0

调用 transferFrom 的是我的 erc721 合约。所以,我改变了测试代码

await contract20.approve(seller, value, {from:buyer});

改成

await contract20.approve(contract721.address, value, {from:buyer});

谢谢你的SylTi

于 2018-10-08T00:45:30.780 回答