bitmap illustration

OpenZeppelin bitmaps.sol is an OpenZeppelin solidity library providing a data structure for managing boolean values, designed to store and manipulate large arrays of booleans, thus dramatically reducing gas cost.

Instead of writing “bool[] array” that occupies 1 storage slot per boolean,
we write “uint256[]” which is 1 storage slot per 256 booleans.

Real-world use cases Link to heading

  • Tracking user claims for an airdrop (hasAddressClaimed: true/false)
  • Voting systems to track voter participation (hasVoted: true/false).

Storage cost comparison Link to heading

  1. Without BitMaps.sol library :
mapping(address => bool) voted;
// in such case , if we have 20,000 users = 20,000 storage slots.
  1. With BitMaps.sol library:
BitMaps.BitMap voted; 
// in this scenario, 20,000 users = 20,000/256 = ~78 storage slots (massive gas savings !!)   

Let’s apply this in a Voting function :


import "@openzeppelin/contracts/utils/struct/BitMaps.sol";

// Use BitMaps for gas optimization
using BitMaps for BitMaps.BitMap;
BitMaps.BitMap private hasVoted;

event VoterStatusUpdated(address indexed voter, bool hasVoted);

function vote(uint256 _candidateIndex) external onlyEligible {
    uint256 voterIndex = uint256(uint160(msg.sender));
    require(!hasVoted.get(voterIndex), "Already voted");
       

    if (_candidateIndex == 0) {
        numVotesForCandidate1++;
    } else {
        numVotesForCandidate2++;
    }

    // Mark as voted using BitMaps
    hasVoted.set(voterIndex);
    voterUSDCBalance[msg.sender] = requiredToken.balanceOf(msg.sender);
    emit VoterStatusUpdated(msg.sender, true);
}