#ethereum #solidity #smartcontracts #openzeppelin
Вопрос:
У меня есть два контракта, которые развернуты отдельно.
Первый контракт.сол
contract FirstContract is ERC721 { using Counters for Counters.Counter; Counters.Counter public _id; constructor(address admin) ERC721("Token Name", "TOKEN") { } function incrementToken() public { _id.increment(); } function currentToken() public view returns (uint256) { return _id.current(); } function mint(address to, uint256 tokenId) public { _mint(to, tokenId); } }
Второй контракт.сол
import "./FirstContract.sol"; contract SecondContract { FirstContract firstContract; constructor(address _address) { firstContract = FirstContract(_address); } // Mint a token to msg.sender function createToken() external { firstContract.incrementToken(); uint256 newTokenId = firstContract.currentToken(); firstContract.mint(msg.sender, newTokenId); } // Transfer the ownership of the token function transferToken(from address, address to, uint256 tokenId) external { // Error here. transferFrom is the method inherited from ERC721 firstContract.transferFrom(from, to, tokenId); } }
После чеканки токена с использованием createToken
in SecondContract
, когда я звоню transferToken
, я получаю следующую ошибку:
ERC721: вызывающий абонент передачи не является владельцем и не утвержден
Это, скорее всего, связано с тем, что SecondContract
msg.sender
при вызове transferFrom
while tx.origin
является фактическим владельцем токена. Я попытался одобрить SecondContract
как одноразовый оператор передачу токена approve(address(this), tokenId)
, но все равно получил ту же ошибку. Я тоже пробовал approve(address(firstContract), tokenId)
или setApproveForAll(address(firstContract), true)
, но результат тот же.
The only way to get this work is if I use _transfer
in FirstContract
:
function transferByAnybody(address from, address to, uint256 tokenId) public { _transfer(from, to, tokenId); }
и вызов этого метода из SecondContract
:
function transferToken(from address, address to, uint256 tokenId) external { firstContract.transferByAnybody(from, to, tokenId); }
что далеко не идеально, потому что любой может вызвать метод передачи, независимо от того, являетесь ли вы владельцем токена или нет.