alpha-wallet-ios icon indicating copy to clipboard operation
alpha-wallet-ios copied to clipboard

Support ERC721Enumerable interface

Open JamesSmartCell opened this issue 3 years ago • 2 comments

Why: Speeds up and simplifies balance query for ERC721.

First detect the ERC721Enumerable interface in your Token interface check:

ERC721Enumerable Interface hash: 0x780e9d63

Then using this contract call:

function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256)

Walk the balance index sequentially to fetch all ERC721 tokenIds for an address.

You will need the balanceOf(address owner) to find the total balance held, then just do 0 -> (total balance -1) and use that for the index in the tokenOfOwnerByIndex call.

Eg:

balanceOf(0x123456...)

returns a balance of 3

for (uint i = 0; i < balanceOf(0x123456...); i++)
{
  balanceArray[i] = tokenOfOwnerByIndex(0x123456..., i);
}

balanceArray could be { 6345, 1295, 5566 }

Which is your TokenId list.

See:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol#:~:text=function%20tokenOfOwnerByIndex(,%7D

Note, for AW Android this doesn't completely replace the event log search, because we still want to find events to populate the activity pane. It does mean though that you don't need to check that the address still holds the tokenId before adding it (after finding the tokenId via a receive log).

JamesSmartCell avatar Sep 19 '22 22:09 JamesSmartCell

It does mean though that you don't need to check that the address still holds the tokenId before adding it

@JamesSmartCell Isn't eventlog fetching for a single contract + address a single call so we can sift through it right away and figure out if the tokenId is still held? Or is there a catch?

hboon avatar Sep 20 '22 06:09 hboon

It does mean though that you don't need to check that the address still holds the tokenId before adding it

@JamesSmartCell Isn't eventlog fetching for a single contract + address a single call so we can sift through it right away and figure out if the tokenId is still held? Or is there a catch?

You'd need at least 2 calls, as you can't just scan incoming logs, you need to scan outgoing. Using this method I'd also check the ownerOf for each token I find in this manner, because you don't know if the event scan is complete; you might only be halfway through the scan, and it massively simplifies the code to do it this way and ensures no false positives.

Enumerable will always be the best method if it's available.

You can mint your own Enumerable tokens on my TokenScript site here: http://smarttokenlabs.duckdns.org/ In AW you can use the mint verb to get more, providing you're minting from the same account that you used to create the contract (ownerOnly modifier on the TS mint function). All the Transfer functions are also onlyOwner (in line with it being a door lock token).

JamesSmartCell avatar Sep 20 '22 13:09 JamesSmartCell