Per eip-721, there's an optional "enumeration extension". So what I did was I called balanceOf
to get the number of tokens owned by the account and called tokenOfOwnerByIndex
in a loop to get each owned token ID.
for(var i = 0; i < balance.toNumber(); i++) {
myERC721Token.tokenOfOwnerByIndex.call(web3.eth.accounts[0], i)
.then((id) => { ... });
}
As a result, it actually listed tokens owned by a user.
However, I am not sure how the code actually works because tokenOfOwnerByIndex
returns mapping variable ownedTokens
, but I've never assigned any value to ownedTokens
! But how can it still return the tokens of an owner? FYI, I mint the token like below.
import "openzeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
contract MyERC721Token is ERC721Token {
function createNewToken(...) {
_mint(msg.sender, index);
}
}
If you take a look at openzeppelin's contract, _mint
that I called here never assigns any value to ownedTokens
. Can anyone see the relationships between the contracts that I can find out why tokenOfOwnerByIndex
is working for me?
Best Answer
ERC721Token inherits from ERC721BasicToken.
When a new token is minted,
_mint
is called from ERC721Token, which then callssuper._mint
which is the_mint
implementation from ERC721BasicToken.super._mint
callsaddTokenTo
from the top level implementation (ERC721Token).addTokenTo
does additional logic to update theownedTokens
array in addition to callingsuper.addTokenTo
, which again references the ERC721Basic token.Thus, by using the
ERC721Token
you get this enumerable set of tokens for a user.In general, you can think of this structure as one contract layer adding additional logic to another layer.
At the bottom you have ERC721BasicToken which by itself implements all of the functions needed for ERC721. Then you have ERC721Token which sits on top of ERC721BasicToken, and overwrites most of the functions with its own logic.
Cleverly, it ALSO includes the old logic using
super.functionName
syntax so that the old logic is run in addition to any new logic. Thus rather than changing the logic of the function, it extends the logic.In this situation, the new logic does all the heavy lifting to make the tokens per owner enumerable.