Hi people.
I’m having some trouble with ERC721’s isApprovedForAll where it always returns false for me.
I know I’m probably doing something wrong in the contract but I can’t figure out what.
Code to reproduce
I wrote a small test case.
First the ERC721 contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyToken is ERC721, ERC721Enumerable, AccessControl {
using Counters for Counters.Counter;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
Counters.Counter private _tokenIdCounter;
constructor() ERC721("MyToken", "MTK") {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
}
function safeMint(address to) public {
require(hasRole(MINTER_ROLE, msg.sender));
_safeMint(to, _tokenIdCounter.current());
_tokenIdCounter.increment();
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
And then the contract utilizing the token contract above:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.6;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
contract Test {
function test(IERC721 token, uint256 id) public {
require(token.isApprovedForAll(token.ownerOf(id), address(this)), "contract not approved as an operator");
// do something
}
}
Environment
I deploy MyToken (A) and Test (B) contracts using account 1
1 then mints 3x MyToken NFTs to account 2
2 executes A.setApprovalForAll(B, true)
1 or 2 executes B.test(A, 0) but the transaction is revered with reason “contract not approved as an operator”
I think that the issue is the way I’m checking if contract B is approved for all transfers of 2 but I’m not exactly sure what I’m doing wrong.
edit: here is a preview of what I described on remix:
edit2:
1 => 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
2 => 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
A => 0xd9145CCE52D386f254917e481eB44e9943F39138
B => 0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8