npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

crambit

v0.1.1

Published

A Solidity library designed to cram as many values into as small a space as possible

Readme

CramBit Open in Gitpod Github Actions Foundry License: MIT

A Solidity library designed to cram as many arbitrary values into as small a space as possible.

This project is somewhat inspired by OpenZeppelin's BitMaps solution, which allows a user to store up to 256 boolean values in a single uint256 variable.

I thought, why just booleans? and decided to cram multiple arbitrary values into the bytes container of your choice. It works by creating a list of packing instructions, i.e. an array of PackBytes structs, that tells the pack function

  1. the value (in byte format) that you want to store, and
  2. the maximum number of bits that that value could contain.

Unpacking a packed variable just performs the reverse, using the packing instructions you already created to unpack your original values.

Why would you want to do something like this? Well, on-chain storage is pretty expensive, so if you can save space by fitting more information into a smaller container, it might be worth the effort.

Example Use Case

One immediate use case came to mind when building this, that being the efficient storage of NFT attributes, especially characters or inventory for Web3 gaming. Characters in games can have dozens, perhaps even hundreds of attributes, with each attribute representing for example 1 of 100 hairstyles, a 32-bit hair color, 1 of 12 face types, etc.

Rather than store all that information on-chain in a complex struct that may take up multiple storage slots, the data could instead be fit into a single 256 bit value or smaller, depending on your data needs.

Overview

Foundry

First, run the install step:

forge install --no-commit joejordan/CramBit

Then, add this to your remappings.txt file:

crambit=lib/CramBit/src/

Node.js

yarn add crambit
# or
npm install crambit

Getting Started

Import the library into your Solidity contract, i.e.

import { CramBit } from "crambit/CramBit.sol";

Packing instructions can be created in several different ways. Ultimately, the pack function just needs an array of PackBytes structs so that it knows what values to pack and how much space to give each value. Here is one example that creates a PackBytes array and packs two values into a single bytes1 variable:

   CramBit.PackBytes1[] memory packInstructions = new CramBit.PackBytes1[](2);
   bytes1 value1 = 0x0f; // 4 bytes max (1111)
   bytes1 value2 = 0x0f; // 4 bytes max (1111)

   // define our packing instructions
   packInstructions[0] = CramBit.PackBytes1({ maxBits: 4, data: value1 });
   packInstructions[1] = CramBit.PackBytes1({ maxBits: 4, data: value2 });

   // pack our data into a bytes1 value
   bytes1 packedBytes1 = CramBit.pack(packInstructions);

Unpacking is pretty easy as well. CramBit has a helper function called packToUnpackMap that will convert your pack instructions into an unpack map, essentially an array of values that represent the maxBits for each packed value. Unpacking can be done like this:

   // generate an unpack map from our packInstructions
   uint8[] memory unpackMap = CramBit.packToUnpackMap(packInstructions);

   // unpack our packed values
   uint8[] memory unpackedValues = CramBit.unpackBytes1(packedBytes1, unpackMap);

   // assert that unpacked values match the original values
   assertEq(unpackedValues[0], uint8(value1));
   assertEq(unpackedValues[1], uint8(value2));

Check out the test directory for more examples.

One important caveat when creating your packing instructions array is that the total maxBits for all of your entries must add up to the same number of bits as the container it's going in, or you're going to get weird numbers back when unpacking.

For example, if you were packing a number of values into in a bytes1 variable, the total number of maxBits for all entries must add up to 8. If you end up with some space at the end, just remember to add an extra entry of any remaining maxBits you need to fill the container. Here's an example:

   CramBit.PackBytes1[] memory packInstructions = new CramBit.PackBytes1[](4);
   uint8 value1 = 7; // 3 bytes max (111)
   uint8 value2 = 2; // 2 bytes max (10)
   uint8 value3 = 1; // 1 bytes max (1)
   bytes1 UNUSED = 0;
   // packed binary value: 111_10_1_??

   // define our packing instructions
   packInstructions[0] = CramBit.PackBytes1({ maxBits: 3, data: bytes1(value1) });
   packInstructions[1] = CramBit.PackBytes1({ maxBits: 2, data: bytes1(value2) });
   packInstructions[2] = CramBit.PackBytes1({ maxBits: 1, data: bytes1(value3) });
   /// @dev important! when your other values require less than the max of the bytes container,
   /// you must include an UNUSED entry with the number of bytes remaining.
   packInstructions[3] = CramBit.PackBytes1({ maxBits: 2, data: UNUSED });

   // pack our data into a bytes1 value
   bytes1 packedBytes1 = CramBit.pack(packInstructions);

Contribute

Contributions are welcome! Open an issue or submit a PR. There is always room for improvement. The instructions below will walk you through setting up for contributions.

Pre-Requisites

You will need the following software on your machine:

Set Up

Clone this repository:

$ git clone https://github.com/joejordan/CramBit.git

Then, inside the project's directory, run this to install dependencies:

$ yarn install

Your environment should now be ready for your improvements.

Security

This code has not been professionally audited by any third parties. If you use this library and include it in a professional audit, please let me know via Twitter Direct Message for inclusion in this documentation.

If you discover any security issues with the library, please report them via Twitter Direct Message.

Disclaimer

This is experimental software and is provided on an "as is" basis. No expressed or implied warranties are granted of any kind. I will not be liable for any loss, direct or indirect, related to the use or misuse of this codebase.

Acknowledgements

  • To my loving and supportive wife who always has my back. ♥

License

CramBit is released under the MIT License.