Supply
FP is one token seen from three chains. It exists on Base; the balances on Ethereum mainnet and Arbitrum are LayerZero OFT deployments, backed one-for-one by FP locked in an adapter contract on Base. Adding the three totals together would count the same tokens twice.
Unified supply
7.10M FP
unified = (Base − locked) + mainnet + Arbitrum. Bridge-locked FP on Base backs everything circulating on Ethereum mainnet and Arbitrum, so the locked balance cancels and the unified figure is Base totalSupply. It reduces exactly only when locked equals the remote supplies; the difference is the residual below.
| Base totalSupply | 7,097,504.277938814911727429 | |
| locked in the adapter | − | 3,970,503.477219 |
| circulating on Base | 3,127,000.800719814911727429 | |
| Ethereum mainnet totalSupply | + | 3,936,503.213959 |
| Arbitrum totalSupply | + | 9 |
| accounted for | 7,063,513.014678814911727429 | |
| Base totalSupply | 7,097,504.277938814911727429 | |
| difference (residual) | 33,991.26326 |
All figures in FP, exact
That residual is stated in full under Bridge, below.
One contract, three names
The token launched on Base as the game token for Fren Pet. It was later renamed VIBE, then Identity.md. Renames only — the same contract, the same holders and the same supply throughout.
The rename is still visible on chain — the deployments answer name() differently, as the table below shows. VIBE is background, not a reading from this snapshot.
It was born on Base and bridged to Ethereum mainnet and Arbitrum as a LayerZero OFT. The genesis supply was 10,000,000 FP; everything below that figure is cumulative destruction.
The game itself is documented by its own site, frenpet.xyz.
Per chain
| chain | name() | symbol() | totalSupply | block | read at (UTC) |
|---|---|---|---|---|---|
| Base | Fren Pet | Fren Pet | 7.10M | 51,961,517 | 2026-09-29 20:06:21 |
| Ethereum mainnet | Identity.md | IMD | 3.94M | 26,085,403 | 2026-09-29 20:06:11 |
| Arbitrum | Fren Pet | FP | 9.00 | 510,132,300 | 2026-09-29 20:06:22 |
The mainnet deployment answers with the Identity.md name and the IMD symbol; the Base and Arbitrum deployments still answer with the Fren Pet names. Same asset, per-deployment metadata — this is what the contracts return, not a mismatch to be corrected. The Base deployment answers symbol() with the full name rather than a ticker; that too is read, not tidied.
Arbitrum holds 9 FP.
Split as of Base block 51961517 / mainnet block 26085403 / Arbitrum block 510132300
Bridge
| adapter contract (Base) | 0xab152db8aaC047b6757fFCF495FfE88d7712690A |
| FP locked in the adapter | 3,970,503.477219 (55.9422% of Base supply) |
| circulating on mainnet + Arbitrum | 3,936,512.213959 |
| residual (locked − circulating) | 33,991.26326 (0.856095% of locked) |
At this snapshot, locked exceeds remote circulation. Locked FP on Base is what backs the balances on the remote chains, so locked should meet or exceed remote circulation; the reverse would mean supply circulating without backing. The script refuses to write a file in that case, so it reaches this page as missing figures rather than as a number.
Destroyed since genesis
2.90M FP
29.02% of the 10,000,000 FP genesis supply
Genesis supply minus Base totalSupply(). Supply that no longer exists.
Scope: the 10,000,000 FP genesis figure only. Historical constant, not a reading from this run: recovering it from chain needs a mint-log sweep, which the free-tier 10-block eth_getLogs cap puts out of reach.
Held at 0x…dEaD
45.377039024748604149 FP
Held at the conventional burn address, still counted inside totalSupply(). Reported separately and never folded into the destruction figure above, which is supply that no longer exists — adding the two would double-count.
Named contract holdings
| contract | address (Base) | FP held | % of Base supply |
|---|---|---|---|
| OFT adapter (bridge lockbox) | 0xab152db8aaC047b6757fFCF495FfE88d7712690A | 3,970,503.477219 | 55.9422 |
| game contract | 0x0e22B5f3E11944578b37ED04F5312Dfc246f443C | 257,504.832647017697957981 | 3.6281 |
| FP/WETH pool (main venue) | 0xDE66c35e01ED8e619Bf092352338ef94f2327337 | 62,697.756982611515043168 | 0.8834 |
| FP/WETH pool (uniswapV2Pair pointer) | 0x29b3a7869E3662D00aaBD89A8ee74B2F703a6a66 | 361.35420354642558878 | 0.0051 |
Balances of addresses this repository already names. Nothing is named here that was not already labelled elsewhere in the repo, and no attempt is made to identify any other holder.
Method
One pinned block per chain, all three heights taken back-to-back and every timestamp read from chain; within a chain every read goes through Multicall3 at the pinned height. Addresses are derived from chain state — mainnet peers() names the Base adapter and the Arbitrum OFT, and the adapter's token() names the Base token. decimals() is read on all three chains. All arithmetic is bigint on raw values; no float touches a figure.
Three pins, taken back-to-back: Ethereum mainnet block 26,085,403, Base block 51,961,517, Arbitrum block 510,132,300 — 11 seconds of wall-clock spread between the earliest and latest, measured from timestamps read from each chain rather than assumed from a block-time formula.
10 controls passed before this file was written, each printing what it expected before it ran. Nothing was written on a failure.
| figure | source |
|---|---|
| unified supply | Base totalSupply() at Base block 51961517, via Multicall3 |
| Base totalSupply | totalSupply() on 0xFF0C532FDB8Cd566Ae169C1CB157ff2Bdc83E105 at Base block 51961517, via Multicall3 |
| Ethereum mainnet totalSupply | totalSupply() on 0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7 at mainnet block 26085403, via Multicall3 |
| Arbitrum totalSupply | totalSupply() on 0x374080d830B66A3E4c8ecbCa846E922A2039A024 at Arbitrum block 510132300, via Multicall3 |
| adapter address | mainnet peers(30184) at mainnet block 26085403, then token() on the peer at Base block 51961517 |
| FP locked | balanceOf(adapter) on 0xFF0C532FDB8Cd566Ae169C1CB157ff2Bdc83E105 at Base block 51961517, via Multicall3 |
| destroyed since genesis | 10,000,000 FP genesis minus Base totalSupply() at Base block 51961517 |
| 0x…dEaD balance | balanceOf(0x…dEaD) on 0xFF0C532FDB8Cd566Ae169C1CB157ff2Bdc83E105 at Base block 51961517, via Multicall3 |
| named contract holdings | balanceOf(address) on 0xFF0C532FDB8Cd566Ae169C1CB157ff2Bdc83E105 at Base block 51961517, via Multicall3 |
Mainnet pool
A Uniswap v4 pool on Ethereum mainnet pairs native ETH with IMD. A v4 pool is not a contract — there is no address to call. It is identified by a poolId, and its state is held in the PoolManager singleton.
| poolId | 0xb07d640fd9e2eb9dc81b953c8e4fd006bdfeaf276010fb5418eb763ca15abfb3 |
| currency0 | 0x0000000000000000000000000000000000000000 |
| currency1 | 0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7 |
| fee | 10000 |
| tickSpacing | 200 |
| hooks | 0x0000000000000000000000000000000000000000 |
| PoolManager | 0x000000000004444c5dc75cB358380D2e3dE08A90 |
Two of those fields are the zero address and they mean different things. currency0 is the zero address because in Uniswap v4 that is the sentinel for native ETH — it is not a burn address and not WETH. hooks is the zero address because there is no hook contract: eth_getCode at that address returns 0 bytes at this snapshot's block.
fee is one of the five fields the poolId is the hash of.
The poolId is keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks)). It is established twice before this file is written: read from topics[1] of the pool's Initialize log, and recomputed from the five fields above. A poolId is the hash of its key, so one leg alone is not enough.
The Initialize log is at block 25,640,607, transaction 0x95f51e7d456c9df25ba6fe56569e08a5f7d3e781f4d34ed532fb191dc2ceabd1.
Full-range liquidity added
3 ModifyLiquidity events added liquidity to this poolId, each spanning the full tick range available at tickSpacing 200:
| block | liquidityDelta | tickLower | tickUpper | transaction |
|---|---|---|---|---|
| 25,771,754 | 53336150074551724 | -887200 | 887200 | 0xa569cee5aeb9449536eac99b44822f2c5a68d25a9f15bcbe97a44111198974d8 |
| 25,771,773 | 7235639113319749967087 | -887200 | 887200 | 0x3c1e7ece5bd995d08f495ffb71d37c314599da905106da42451ac8e711bfb9b1 |
| 25,771,799 | 157400387495567549793 | -887200 | 887200 | 0x038773e897a94593d3d128f824be22f146b8aacd4fd4df1d75db7c3422281ab8 |
-887200 and 887200 are the widest multiples of tickSpacing 200 lying within ±887272.
The v3 position and the v3 pool
These are two objects and the difference is exact.
Position #1167726 on the Uniswap v3 position manager 0xC36442b4a4522E871399CD717aBDD847Ab11FE88 no longer exists. It held 7314696929747056528126 units of liquidity, added across 2 IncreaseLiquidity events at blocks 24,179,225 and 25,700,675. 1 DecreaseLiquidity event at block 25,771,773 removed 7314696929747056528126, leaving a residual of 0. Fees were collected and the NFT was burned in the same block, recorded as a Transfer to the zero address. At this snapshot's block ownerOf(1167726) reverts with ERC721: owner query for nonexistent token, and positions(1167726) reverts with Invalid token ID.
The Uniswap v3 WETH/IMD pool at 0xD6A822D028bbf7b6EDfA1533e110Ee40c08551d9 is a separate object from the position. Its liquidity() at this snapshot's block is nonzero, from positions this snapshot does not enumerate.
One transaction
The v3 DecreaseLiquidity, the final Collect, the burn Transfer and the largest of the 3 v4 ModifyLiquidity events are 4 log entries of a single transaction receipt: 0x3c1e7ece5bd995d08f495ffb71d37c314599da905106da42451ac8e711bfb9b1, block 25,771,773.
Read at Ethereum mainnet block 25,781,611 (2026-08-18 11:15:35 UTC), finalized. 8 controls passed before this file was written.