Openzeppelin ERC20 сделать откат

мое намерение состоит в том, чтобы токен 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]

пожалуйста, проверьте мой полный код здесь


person Twibap    schedule 04.10.2018    source источник


Ответы (1)


тот, кто вызывает transferFrom, - это мой контракт на erc721. Итак, я меняю тестовый код

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

изменить на

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

спасибо за SylTi

person Twibap    schedule 08.10.2018