voidcashdocs

Deployments

The network, every voidcash contract address on Elysium, the listed tokens and their limits, the Volta contracts VOID trades on, the public bundler and indexer, and how to check all of it on-chain.

Network

FieldValue
NetworkElysium, Kinetiq's Arbitrum Orbit chain on Hyperliquid's HyperEVM
Chain ID99901
RPC URLhttps://rpc.volta.family (Volta's public endpoint; the app and the SDK use it by default)
Explorerelysium.kinetiq.xyz/explorer (Blockscout)
Native currencyHYPE, 18 decimals; gas is paid in HYPE
Appvoidcash.io, wallet at /app

What matters about Elysium when you build on it:

  • Blocks follow transactions. Elysium makes a block only when there are transactions, so block numbers are not a clock. voidcash's contracts measure time with block.timestamp.
  • Log queries are capped. eth_getLogs on the public endpoints accepts at most 10,000 blocks per call, and heavy ranges can fail before that. The SDK reads in ranges of 5,000 blocks and splits any range the RPC refuses.
  • No websocket on the public RPC. Read logs with eth_getLogs, or use the indexer.
  • Contract size limit. Elysium enforces the 24,576-byte limit on deployed code.

voidcash contracts

ContractAddressWhat it is
PrivateVault (proxy)0x5535fa0d95E4e03783C3A5d693E2f7225e6d23d4The vault, and the only address users and integrators need: an ERC-1967 proxy holding the shielded HYPE and listed tokens, the note tree, nullifiers, the key registry, pending exits, the per-token books and the vault's ERC-4337 account
PrivateVault (implementation)0x45648A8aE69C2c4EAE0dc5727E66F8921F771181The code behind the proxy: vault v2 (multi-asset), installed on 2026-11-05. The upgrader can point the proxy at another implementation; read the current one from the proxy's implementation slot
HonkVerifier0x29688590CA80928f8f0039334D9f723180cd482aUltraHonk verifier of the v2 transact circuit (three notes in, four out, 14 public inputs), an immutable of the vault's implementation
Poseidon2 hasher0x46c60Cbe41b4A18751b85b7cDfC8d03BeC35E9e5Poseidon2 over BN254 (the poseidon2-evm Yul contract), used by the note tree and for HYPE note commitments
Poseidon2Hash40xdf0EDcbbBBdd91ec58a7dBbc2b7457d553Aa2bc0The four-input Poseidon2 hash of token note commitments, as Noir computes it. Stateless, no owner; an immutable of the vault's implementation
FeeCollector0x145618DF0662dCd38a2Cf2AC4d24Dfe1FC8A4991Receives the HYPE exit fees and unused gas from the vault; pays half to the team and spends half buying VOID and burning it
VOID0xD31B21Cb80E431AC996269deC31A40fCf048B77fThe token: an ERC-20 launched on Volta, paired with native HYPE. Listed in the vault since 2026-11-05 (see Listed tokens); not needed to use voidcash

The verifier links two external libraries. They were deployed with the first verifier, and the v2 verifier links the same two:

Every function, event and error is on Contracts.

Roles and parameters

The vault has three roles and a token fee recipient. The fee collector has an owner and a team recipient. VOID's creator NFT on Volta decides who receives the creator's share of VOID's swap fee. One address holds all of them, 0xb06aBb2a232e6e7e91b37ADf79116c41AD4b879a:

RoleWhat it can do
Vault DEFAULT_ADMIN_ROLEGrant and revoke every role, set the large-exit threshold, change the fee collector, list tokens, set each token's limits and the token fee recipient
Vault UPGRADER_ROLEReplace the vault's implementation, with no delay
Vault GUARDIAN_ROLEPause every spend and payout, stop new shields of every asset or of one token, stop or resume an exit not yet paid
Vault tokenFeeRecipientReceives the 1% exit fees taken in tokens, through sweepTokenFees
FeeCollector ownerChange the team's recipient, hand ownership on or renounce it
FeeCollector team recipientReceives the team's half of what reaches the collector
VOID creator NFT holderReceives the creator's share of VOID's swap fee on Volta

What each role can and cannot reach is on Trust model.

ParameterValue
largeExitThreshold1,000 HYPE: a HYPE exit paying out more waits 24 hours. Set at deployment, unchanged by the upgrade
feeCollector0x145618DF0662dCd38a2Cf2AC4d24Dfe1FC8A4991
tokenFeeRecipient0xb06aBb2a232e6e7e91b37ADf79116c41AD4b879a, the fee collector's team recipient, set by the upgrade
EIP-712 domainname voidcash, version 1, chain ID 99901, verifying contract the vault proxy
paused, entriesPausedfalse, false

Listed tokens

The vault's admin lists tokens one at a time (listToken). A listed token is never removed, since its notes stay spendable; the guardian can close it to new deposits (setTokenEntriesPaused), and the vault's own entries pause closes HYPE and every token at once. Each token has two limits, in its own units: an exit paying out more than its large-exit threshold waits 24 hours, and so does an exit that would take the exits paid in the current 24-hour window above its window cap. The guardian can stop a waiting exit.

TokenAddressDecimalsLarge-exit thresholdWindow cap (per 24 hours)Listed
VOID0xD31B21Cb80E431AC996269deC31A40fCf048B77f185,000,000 VOID (0.5% of the supply at launch)25,000,000 VOID2026-11-05, block 1,055,851
VOLTA0x0f79931689Af199e7CF868ed1107bBA2C83c68f7185,000,000 VOLTA (about 0.5% of the supply when listed)25,000,000 VOLTA2026-11-06, block 1,640,196
BLOB0x9a9815Af521149E8D982791703A31bca2F95f534185,000,000 BLOB (0.5% of the supply)25,000,000 BLOB2026-11-07, block 2,101,705
YIELDEX0x301eB259De132D592966fe0712DB75b27792A68a185,000,000 YIELDEX (about 0.5% of the supply when listed)25,000,000 YIELDEX2026-11-08, block 2,145,403

BLOB pays its holders dividends in HYPE, which each holder claims from the token; BLOB held in the vault earns none for its owners, since the dividends that accrue to the vault cannot be claimed.

A token's exit fee is 1% of what leaves, in the token, and goes to the token fee recipient, not to the fee collector: the VOID burn is fed by HYPE exit fees only. Gas for every private action is paid in HYPE, so a private token action also spends a private HYPE note. Read the live values with tokenConfig(token) (see below), or every listing and change from the vault's TokenListed and TokenLimitsSet events.

Unused contract

LaunchBuyer (0x7534Ba20DC4bFAFAE4650B2Dc67A0d02EC1794A5) was deployed by the same deployer for a launch plan that was then dropped. It has no owner, holds nothing between calls, and nothing in voidcash uses it.

Volta and the VOID pool

VOID launched on Volta, a launchpad on Elysium built on Flaunch's contracts. It trades on a Uniswap v4 pool against native HYPE from its first block; Volta has no bonding curve. VOID is Volta launch number 232. Its page on Volta is https://volta.family/token/ followed by VOID's address.

ContractAddressWhat it is
PositionManager0x3aB88DDc3CF2A012af88B60828edb4553697E5dCVolta's Uniswap v4 hook: creates launches and their pools, takes each swap's fee and splits it
Creator NFT (Flaunch)0xac466Ee5CEdD012eB750DBDA0B935F8B997402c7One NFT per launch; creates the token. Its holder receives the creator's share
FeeEscrow0x3D36Beb546E451584736957F97E7EE9D2aCbD9a5Holds the creator's and Volta's shares until their owners withdraw them
FeeVault0xB074897161E8b00d97d3F4163f73de12f7B8f4BaHolds each pool's buyback share until Volta's executor spends it
Token implementation0x541Ef1674D3Cc64D0ab1f14381cA5970FD10B554Every launch, VOID included, is a 44-byte clone of it
FeeExecutor0xD68D650DAFb9BA8517DA430f7f0a94e942E89c41Spends the FeeVault on buying VOID back and burning it; only Volta's operators can call it
InternalSwapPool0x5C1d9b6Dc78CC31A6D08ada1d1c68dA148759c0CSells the fees taken in VOID back to later buyers

VOID's pool, as the fee collector checks it in its constructor:

PoolKey fieldValue
currency00x0000000000000000000000000000000000000000 (native HYPE)
currency1VOID, 0xD31B21Cb80E431AC996269deC31A40fCf048B77f
fee0: the hook takes the swap fee
tickSpacing60
hooksVolta's PositionManager, 0x3aB88DDc3CF2A012af88B60828edb4553697E5dC
Pool id0xe488e93cba1cbbb1493d898a4f352571d0d96ddc4902f5449d07ad33ee34ee08

Every swap pays a 1% fee, fixed for the life of the pool. Volta keeps 30% of it; of the rest, half goes to the creator NFT's holder and half to Volta's buyback, which buys VOID and burns it. See VOID.

Shared infrastructure

ContractAddress
Uniswap v4 PoolManager (Elysium's, where Volta's pools live)0xE2e105d3F7209A9DA11f83cCf3E7398a753823F1
ERC-4337 EntryPoint v0.80x4337084D9E255Ff0702461CF8895CE9E3b5Ff108
CreateX0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed
Multicall30xcA11bde05977b3631167028862bE2a173976CA11

Public services

Bundler

Private actions reach the chain as ERC-4337 UserOperations whose sender is the vault. No public bundler serves Elysium, so voidcash runs its own: Alto 0.0.21, Pimlico's open-source bundler, behind a gate.

FieldValue
Endpointhttps://bundler.voidcash.io (JSON-RPC over POST at / or /rpc; GET /health)
EntryPointv0.8, 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108
Methodseth_chainId, eth_supportedEntryPoints, eth_estimateUserOperationGas, eth_sendUserOperation, eth_getUserOperationReceipt, eth_getUserOperationByHash, pimlico_getUserOperationGasPrice, pimlico_getUserOperationStatus
Accepted operationsSender is the vault; no factory, no paymaster, no EIP-7702 authorization
Rate limits120 requests per minute per client address; 20 per minute for eth_estimateUserOperationGas and eth_sendUserOperation
Request size64 KB. A vault operation is about 25 KB: its proof is 9,152 bytes
BrowsersCORS is answered for the app's origins only. Servers and the SDK in Node.js can call it from anywhere

The gate forwards only the request body, so no client header reaches Alto. One private action makes about 35 requests: a gas price, an estimate, the send, and receipt polls every 2 to 5 seconds. Any bundler that speaks Pimlico's RPC methods and supports EntryPoint v0.8 on Elysium can be used instead. See Gas.

Indexer

The indexer serves the vault's events, the same for everyone, so wallets do not have to read the whole chain.

EndpointWhat it returns
GET https://indexer.voidcash.io/events?from=<block>[&after=<block>:<logIndex>]{ events, next, head }: up to 2,000 vault events in chain order
GET https://indexer.voidcash.io/status{ chainId, syncedThrough, lastConfirmedAt }
GET https://indexer.voidcash.io/ready200 once the first confirmation is done, 503 before
GET https://indexer.voidcash.io/health200 while the service runs

The API is described on Integrations.

Check it on-chain

Everything above can be read with Foundry's cast and the public RPC. Set the addresses from the tables on this page:

export ETH_RPC_URL=https://rpc.volta.family
VAULT=0x…        # PrivateVault (proxy)
COLLECTOR=0x…    # FeeCollector
VOID=0x…         # VOID
ACCOUNT=0x…      # an address whose roles you want to check

The vault's code and wiring:

# The implementation the proxy runs now (ERC-1967 implementation slot)
cast storage $VAULT 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc

# Immutables of that implementation
cast call $VAULT "verifier()(address)"
cast call $VAULT "hasher()(address)"
cast call $VAULT "hasher4()(address)"
cast call $VAULT "entryPoint()(address)"

# State of the proxy
cast call $VAULT "feeCollector()(address)"
cast call $VAULT "largeExitThreshold()(uint256)"
cast call $VAULT "paused()(bool)"
cast call $VAULT "entriesPaused()(bool)"
cast call $VAULT "eip712Domain()(bytes1,string,string,uint256,address,bytes32,uint256[])"

The listed tokens:

# listed, entriesPaused, largeExitThreshold, windowCap
cast call $VAULT "tokenConfig(address)(bool,bool,uint256,uint256)" $VOID
# backing, pendingExits, feesAccrued, windowStart, windowOut
cast call $VAULT "tokenBook(address)(uint256,uint256,uint256,uint64,uint256)" $VOID
cast call $VAULT "tokenFeeRecipient()(address)"
cast call $VAULT "TOKEN_WINDOW()(uint256)"   # 86400

# What the vault holds of the token: at least backing + pendingExits + feesAccrued
cast call $VOID "balanceOf(address)(uint256)" $VAULT

The vault's roles:

# DEFAULT_ADMIN_ROLE is 0x00…00
cast call $VAULT "hasRole(bytes32,address)(bool)" 0x0000000000000000000000000000000000000000000000000000000000000000 $ACCOUNT
cast call $VAULT "hasRole(bytes32,address)(bool)" $(cast keccak UPGRADER_ROLE) $ACCOUNT
cast call $VAULT "hasRole(bytes32,address)(bool)" $(cast keccak GUARDIAN_ROLE) $ACCOUNT

The roles use OpenZeppelin AccessControl, which does not list a role's members. To find every holder, read the vault's RoleGranted and RoleRevoked events from its deployment block, 454409, in ranges of at most 10,000 blocks. A change of implementation shows as an Upgraded event.

The fee collector and VOID:

cast call $COLLECTOR "owner()(address)"
cast call $COLLECTOR "teamRecipient()(address)"
cast call $COLLECTOR "token()(address)"
cast call $COLLECTOR "poolId()(bytes32)"
cast call $COLLECTOR "totalBurned()(uint256)"

cast call $VOID "name()(string)"        # "voidcash"
cast call $VOID "symbol()(string)"      # "VOID"
cast call $VOID "decimals()(uint8)"     # 18
cast call $VOID "totalSupply()(uint256)"

# VOID is a clone of Volta's token implementation: 44 bytes that delegate to it
cast code $VOID
# 0x3d3d3d3d363d3d37363d73541ef1674d3cc64d0ab1f14381ca5970fd10b5545af43d3d93803e602a57fd5bf3

# The launch and its creator NFT
NFT=0xac466Ee5CEdD012eB750DBDA0B935F8B997402c7
cast call $NFT "tokenId(address)(uint256)" $VOID    # 232
cast call $NFT "ownerOf(uint256)(address)" 232

The vault's own deposit on the EntryPoint. Every private operation adds its gas fee to it, the EntryPoint takes the gas used from it, and sweepFees sends what is left to the fee collector:

cast call 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108 "balanceOf(address)(uint256)" $VAULT

How it was deployed

The deploy scripts are in contracts/script, and their records in contracts/deployments: 99901.planned.json (addresses computed in advance), 99901.verifier.json, 99901.vault.json, 99901.upgrade-v2.json (the upgrade to v2) and 99901.json (every current address).

The first deployment, with vault v1 (HYPE only):

ContractBlockDate (UTC)
RelationsLib, ZKTranscriptLib453473, 4535362026-11-04
HonkVerifier (v1, since replaced)4536542026-11-04 16:20
Poseidon2 hasher4540112026-11-04
PrivateVault implementation (v1, since replaced)4543342026-11-04
PrivateVault proxy4544092026-11-04 16:22
VOID, on Voltalaunch 2322026-11-04
FeeCollector5280762026-11-04 19:45

Plan. Deploy.s.sol's plan computes the hasher's, the vault's and the fee collector's addresses before anything is sent. They go through CreateX's CREATE3 with a salt only the deployer can use, which includes the chain ID and the label voidcash-v1. Each address therefore depends only on the deployer, the chain and the label, not on the bytecode. VOID's address cannot be planned: Volta derives it from the launch's number.

The verifier. DeployVerifier.s.sol deploys HonkVerifier and its two libraries. It refuses a verifier source other than the pinned Barretenberg 5.2.1 build, or one compiled with anything but solc 0.8.38.

The vault. Deploy.s.sol's run first checks the verifier: its source carries Barretenberg's five-claim opening, and the deployed code is the 10,000-run build of that source and accepts the repository's real proof. It checks that CreateX and the EntryPoint are the canonical code. It then deploys the hasher (and checks it hashes as the circuit does), the vault's implementation, and the proxy, initialized with the 1,000 HYPE threshold, the fee collector's planned address and the three roles. The vault does not need VOID: shields, private sends and exits work from this step on.

VOID. Launched on Volta with a 1% swap fee, no anti-snipe fee, trading open at once, and the creator's side of the fee split half to the creator and half to Volta's buyback. Before launching, the script checks that Volta's PositionManager, creator NFT, FeeEscrow and token implementation, and the PoolManager, carry the exact code the fork tests ran against, and how they point at each other.

The fee collector. deployCollector checks the launch on-chain (the clone, the pool key, the fee and its split, the creator NFT, the name, symbol, decimals and supply) and deploys FeeCollector at the address the vault already pays. HYPE swept there before it existed is split by its first collect or payTeam.

Build settings: Solidity 0.8.38 for the Cancun EVM, OpenZeppelin Contracts and Contracts Upgradeable 5.7.0. The vault is compiled at 200 optimizer runs to fit the contract size limit: the v2 implementation's deployed code is 23,413 bytes (cast codesize). The verifier and every other contract are compiled at 10,000.

After the deploy, the deployer deposited 0.001 HYPE for the vault on the EntryPoint (block 553934). A bundler's gas estimate is simulated at a tiny gas price and still needs a prefund from the account's deposit; this deposit lets it succeed. Every real operation still pays its own gas from the notes it spends. sweepFees() withdraws the whole deposit, so the keeper tops it up to 0.001 HYPE after every sweep.

The upgrade to v2

On 2026-11-05 the vault was upgraded in place to v2, which adds listed ERC-20 tokens. The proxy, its address, the note tree and every HYPE note stayed as they were: HYPE notes keep their commitment, and v2 only appends storage. A proof made for the v1 circuit fails under v2, so the app, the SDK, the indexer and the keeper switched at the same time.

Every transaction came from the address that holds the admin and upgrader roles, 0xb06aBb2a232e6e7e91b37ADf79116c41AD4b879a, between 20:06 and 20:08 UTC:

StepTransactionBlockResult
DeployVerifier.s.sol: the v2 HonkVerifier0xd69e85b0…d4201,054,9610x29688590CA80928f8f0039334D9f723180cd482a
UpgradeV2.s.sol: Poseidon2Hash40x88cf45ff…b9cc1,055,3940xdf0EDcbbBBdd91ec58a7dBbc2b7457d553Aa2bc0
The v2 implementation0xebdaefaf…246a1,055,5300x45648A8aE69C2c4EAE0dc5727E66F8921F771181
upgradeToAndCall(implementation, "")0xeccfe4d2…fd0a1,055,593The proxy runs v2 (Upgraded)
setTokenFeeRecipient0x6dd5aa88…ba241,055,713The team's recipient receives token exit fees
listToken(VOID, 5,000,000 VOID, 25,000,000 VOID)0xb1b0f211…a4221,055,851VOID listed (TokenListed)

The implementation before the upgrade was 0x942b5DF5f8D19Ea95b006F0e3AF947909453622b.

The verifier. DeployVerifier.s.sol refuses a verifier source other than the pinned Barretenberg 5.2.1 build of the v2 circuit, or one compiled with anything but solc 0.8.38, and requires the deployed verifier to accept the repository's real 14-input proof.

Before broadcasting, UpgradeV2.s.sol checks that the proxy runs the expected v1 implementation, that the verifier is new, has the size of the 10,000-run build and accepts the real proof, that the token has code, 18 decimals or fewer and a supply below 2^120, and that the sender holds the admin and upgrader roles.

The upgrade. It deploys Poseidon2Hash4 and the implementation, under the live EIP-712 name, hasher and EntryPoint. The implementation's constructor refuses a four-input hasher that does not return Noir's hash_4(1, 2, 3, 4) (WrongHasher). It then calls upgradeToAndCall with no initializer, sets the token fee recipient and lists VOID.

After, it checks that the tree's root, the HYPE books, the HYPE threshold, the fee collector, both pauses, the EIP-712 name, the hasher, the EntryPoint, the roles and the vault's HYPE balance are unchanged, that hasher4 and the verifier are the new ones, and that VOID is listed, open, with its limits. It writes deployments/99901.upgrade-v2.json.

On this page