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

@skenaja/solpi

v0.1.0

Published

On-chain π for Solidity. Machin's formula (69 exact digits) and a 4,200-digit lookup table, in 42 chunks of 100. Useless. Correct. Nice.

Readme

solpi

On-chain π for Solidity. Computed (69 exact digits) and tabulated (4,200 digits, in 42 chunks of 100).

       ____  _
      |  _ \(_)
      | |_) |_
      |  __/| |
      |_|   |_|     π · π · π · π · π · π · π · π · π

A single contract, Pi, with two ways to ask for the most famous transcendental number in mathematics:

| function | returns | source | | ----------------------- | --------------------------------------------- | ------------------------------- | | computePi() | π · 10^70 as uint256 (69 digits exact) | Machin's 1706 formula, on-chain | | pi(uint256 chunk) | 100 fractional digits as string | precomputed bytecode lookup |


Install

As a Foundry dependency

forge install skenaja/solpi

Then in your contract:

import {Pi} from "solpi/contracts/Pi.sol";

contract MyContract {
    Pi public immutable piContract;

    constructor() {
        piContract = new Pi();
    }

    function fetchSliceOfPi(uint256 chunk) external view returns (string memory) {
        return piContract.pi(chunk);
    }
}

As an npm package

npm install @skenaja/solpi

Then in your contract (assumes Hardhat-style remappings):

import {Pi} from "@skenaja/solpi/contracts/Pi.sol";

API

SCALE (constant)

uint256 public constant SCALE = 10**70;

The fixed-point scale used by computePi(). One decimal place of π per power of ten.

DIGITS, CHUNK_SIZE, CHUNKS (constants)

uint256 public constant DIGITS     = 4200;
uint256 public constant CHUNK_SIZE = 100;
uint256 public constant CHUNKS     = 42;

Invariant: DIGITS == CHUNK_SIZE * CHUNKS.

computePi()

function computePi() external pure returns (uint256);

Computes π to 69 exact decimal digits using Machin's formula (John Machin, 1706):

π = 16·arctan(1/5) − 4·arctan(1/239)

Each arctan(1/x) is summed via the Gregory–Leibniz series in scaled-uint256 fixed-point at SCALE = 10^70. The loop bails one Taylor term short of uint256 overflow; cumulative truncation costs the 70th decimal place. The remaining 69 digits are bit-exact.

Returns the integer 31415926535897932384626433832795028841971693993751058209749445923078164….

pi(uint256 chunk)

function pi(uint256 chunk) external pure returns (string memory);

Returns 100 fractional digits of π by chunk index.

  • pi(0) → digits 1..100 (the famous "1415926535…")
  • pi(1) → digits 101..200
  • pi(41) → digits 4101..4200
  • pi(42+) → reverts with ChunkOutOfRange(chunk, 41)

Reconstructing the full 4,200-digit fractional expansion is just pi(0) ‖ pi(1) ‖ … ‖ pi(41).


Why?

For the lulz.

Useful applications include:

  • on-chain art / generative seeds where π's digits are aesthetically required
  • nothing else, really

This contract is not a source of cryptographic randomness. π is the least-random number in mathematics: every digit is exactly where it has always been, and where any sufficiently determined attacker can also find it.


Development

Setup

git clone --recursive https://github.com/skenaja/solpi.git
cd solpi

If you already cloned without --recursive:

git submodule update --init --recursive

Build

forge build

Test

forge test                          # unit + fuzz, default (1024 fuzz runs)
FOUNDRY_PROFILE=ci forge test       # 8192 fuzz runs, deeper invariants
forge test --gas-report             # gas usage per function
forge coverage                      # line coverage

Format

forge fmt

How it's tested

  • Unit tests for known reference values (first 100 digits, last 100 digits, leading 69 of computePi).
  • Fuzz tests over the chunk index space — every valid chunk must return exactly 100 ASCII decimal digits; every invalid chunk must revert with the typed ChunkOutOfRange error.
  • Cross-validation between computePi() and pi(0) — the first 69 fractional digits must agree byte-for-byte across the two independent code paths.
  • Property tests over the full 4,200-digit string — every byte is in '0'..'9', no chunk overlaps another, concatenation reconstructs the table exactly.
  • Invariants on the DIGITS == CHUNK_SIZE × CHUNKS constant relationship.
  • Fixture-based verification — a separately-sourced 4,200-digit reference is loaded at runtime via vm.readFile and compared against the contract's embedded constant.

Gas report

Generated with forge test --gas-report at the pinned compiler version (solc 0.8.27, optimizer on, 200 runs):

| Function | Min | Avg | Median | Max | notes | | ------------ | ----: | -----: | -----: | ----: | --------------------------------------- | | SCALE() | 266 | 266 | 266 | 266 | constant getter | | DIGITS() | 216 | 216 | 216 | 216 | constant getter | | CHUNK_SIZE() | 238 | 238 | 238 | 238 | constant getter | | CHUNKS() | 282 | 282 | 282 | 282 | constant getter | | pi(chunk) | 381 | 23,062 | 27,093 | 27,093 | 100-byte memcpy from bytecode constant | | computePi() | 69,252 | 69,252 | 69,252 | 69,252 | 75 Taylor terms across two arctans |

| Deployment cost | Runtime size | Initcode size | EIP-170 margin | | --------------: | -----------: | ------------: | -------------: | | 1,195,526 | 5,282 B | 5,310 B | 19,294 B |

Reading is cheap: pi(chunk) is ~27k gas (≈ a single SLOAD + a small loop), constant getters are sub-300 gas. Computing is the expensive bit: computePi() runs 54 + 20 Taylor terms in fixed point, including the overflow-guard branches, for ~69k gas — still well under one block-fraction.


License

MIT.


A historical note

| year | who | digits | medium | | ---------- | ----------- | --------------- | --------------------- | | ~250 BC | Archimedes | 3 | 96-gon, by hand | | 263 AD | Liu Hui | 5 | 3072-gon | | ~1400 | Madhava | 11 | infinite series | | 1706 | Machin | 100 | THIS formula, ink | | 1873 | Shanks | 527 | last 180 wrong, oops | | 1949 | ENIAC | 2,037 | 70 hours, vacuum tubes | | 2019 | Iwao | 31,400,000,000,000 | Google Cloud | | 2026 | this repo | 4,200 | EVM bytecode |

Progress is not monotone.