Openzeppelin ERC20进行还原

时间:2018-10-04 07:34:58

标签: solidity revert erc20 open-zeppelin

我的意图是使ERC721令牌只能通过我的ERC20令牌进行转移

转移流程是

  1. 买方批准将ERC20授予卖方。
  2. 卖方将ERC721转让给买方。
  3. 我的ERC721令牌的转移功能首先将ERC20从买方转移到卖方,然后将ERC721从卖方转移到买方。

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]

请检查我的完整代码here

1 个答案:

答案 0 :(得分:0)

一个电话transferFrom是我的erc721合同。 所以,我更改测试代码

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

更改为

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

感谢您的SylTi