← Back to list

Bit Manipulation in ERC721A

In a normal ERC721 smart contract if you wanted to store information about a specific user.

Saphekhan · 2023-05-21 19:17 · 12 claps · 3.8 min read
#erc721a #bit-manipulation #smart-contracts #blockchain-technology #token
Open on Medium ↗
Wiki topics: CRY · Crypto & Web3

Bit Manipulation in ERC721A

In a normal ERC721 smart contract if you wanted to store information about a specific user.

like balance, No. of tokens minted, No. of tokens burned, some amount of auxiliary data for a user.

And also wanted to store some other information about the tokenId like Address of user, start timestamp, is it burned, some extra data about it

The first approach you would take is to create a mapping of address to structs, something like

mapping (address => struct) _addressData;

Similarly, for the tokenId the approach you would take

mapping(uint=>struct) _ownership;

Drawback of this approach is that you create a struct and every time you do write operations it’s going to cost a heavy amount of gas.

Now imagine a way to store all the information of struct inside just a simple uint256 variable.

ERC721A has handled this really impressively using the concept of bit manipulation.

We have a mapping

mapping (address => uint256) _packedAddressData;

Bit reservations in uint256.

In uint256 for each piece of information ERC721A have reserved the sets of 64 bits. First 63 bits are reserved for the balance of the user. Next from 64–127 bits are reserved for the number of tokens minted and so on..

ERC721A uses uint256 but for the sake of presenting things visually we will use uint16 variable called _packedAddressData.

uint16 _packedAddressData

uint16 _packedAddressData

In our uint16 First four bits are reserved for balance and so on.

Information retrieval

To store and retrieve information in such a form we use fundamental bitwise operations

  1. Bit Masking

2. Left shift

3. Right Shift

4. Bitwise and (&)

5. Bitwise or (|)

Since we are storing information in sets of 4 bits, we will create a bitmask of 16 bits where first four bits are Up rest are off.

This can be done easily by shifting 1 four bits and subtracting one from the answer this will turn on the bits up to fourth bit.

Uint16 _bitmask = (1<<4)-1

(1<<4) = 16

16–1 =15

15 when converted to binary and casted in to uint16 will result in something like this

_bitmask

_bitmask

  1. _blcOf ()

Since the balance is stored in first four bits to get balance of the owner we will do

Bitwise And between _packedAddressData and _bitmask;

1011 when converted to decimal will tell the balance of the owner.

2. _numberMinted ()

We will first apply the right shift to _packedAddressOwner[address] and then & the bitmask.

(packedAddressOwner[address] >> 4) & bitmask;

3. _numberBurned ()

(packedAddressOwner[address] >> 8) & bitmask;

Information storage

Storing information is also a simple process. We will consider the mint function where we store the balance of the owner and number of tokens minted in a single line of code.

_mintTo(quantity)

_packedAddressData[to] += quantity * ((1 << 4) | 1);

Let’s say we wanted to mint 2 tokens in that case

_packedAddressData[to] = 2 * ((1<<4) |1)

_packedAddressData[to] = 2 * (16 |1)

_packedAddressData[to] = 2 * (17)

_packedAddressData[to] = 34

This number when converted to binary results in

ERC-721a Characteristics:

  • Moves initialization of token ownership from the minting stage to transferring stage
  • Is heavily optimized for generative artwork NFT collections
  • Best used for NFTs with a busy mint phase
  • Prioritizes gas savings for the minting phase

Drawbacks of ERC721A:

Costly transfer and burn functions :

While the minting function saves a lot of gas but the transfer function of ERC721A is not efficient at all that each time we want to transfer the tokenId let’s say we want to transfer tokenId 102 to John then the transfer function will go to tokenId 102 and will keep iterating backwards until we find the owner of tokenId102 at tokenId 100.

Then we will decrease the balance of the owner and copy the data of the tokenId100 like tokenURI, change its owner and will paste it into tokenId 102 .

In a nutshell:

  • More expensive for single NFT mints
  • Not ideal for pure utility NFTs that do not have a busy mint phase
  • Each contract can only represent a single type of NFT
  • No support for semi-fungible tokens

References :

https://www.azuki.com/erc721a


메타데이터
post_id
6cf4bfc9e229
slug
bit-manipulation-in-erc721a-6cf4bfc9e229
url
https://medium.com/@saphekhan/bit-manipulation-in-erc721a-6cf4bfc9e229
canonical_url
https://medium.com/@saphekhan/bit-manipulation-in-erc721a-6cf4bfc9e229
author_url
https://medium.com/@saphekhan
status
ok
fetched_at
2026-07-26 09:52:31