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
| Field | Value |
|---|---|
| Network | Elysium, Kinetiq's Arbitrum Orbit chain on Hyperliquid's HyperEVM |
| Chain ID | 99901 |
| RPC URL | https://rpc.volta.family (Volta's public endpoint; the app and the SDK use it by default) |
| Explorer | elysium.kinetiq.xyz/explorer (Blockscout) |
| Native currency | HYPE, 18 decimals; gas is paid in HYPE |
| App | voidcash.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_getLogson 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
| Contract | Address | What it is |
|---|---|---|
PrivateVault (proxy) | 0x5535fa0d95E4e03783C3A5d693E2f7225e6d23d4 | The 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) | 0x45648A8aE69C2c4EAE0dc5727E66F8921F771181 | The 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 |
HonkVerifier | 0x29688590CA80928f8f0039334D9f723180cd482a | UltraHonk verifier of the v2 transact circuit (three notes in, four out, 14 public inputs), an immutable of the vault's implementation |
| Poseidon2 hasher | 0x46c60Cbe41b4A18751b85b7cDfC8d03BeC35E9e5 | Poseidon2 over BN254 (the poseidon2-evm Yul contract), used by the note tree and for HYPE note commitments |
Poseidon2Hash4 | 0xdf0EDcbbBBdd91ec58a7dBbc2b7457d553Aa2bc0 | The four-input Poseidon2 hash of token note commitments, as Noir computes it. Stateless, no owner; an immutable of the vault's implementation |
FeeCollector | 0x145618DF0662dCd38a2Cf2AC4d24Dfe1FC8A4991 | Receives the HYPE exit fees and unused gas from the vault; pays half to the team and spends half buying VOID and burning it |
| VOID | 0xD31B21Cb80E431AC996269deC31A40fCf048B77f | The 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:
| Library | Address |
|---|---|
RelationsLib | 0xfDa84E5d3E0d47a0de359E03c4a730F020E49456 |
ZKTranscriptLib | 0x534c4774535e161e2b68f42FeD005378bc4DADFc |
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:
| Role | What it can do |
|---|---|
Vault DEFAULT_ADMIN_ROLE | Grant 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_ROLE | Replace the vault's implementation, with no delay |
Vault GUARDIAN_ROLE | Pause every spend and payout, stop new shields of every asset or of one token, stop or resume an exit not yet paid |
Vault tokenFeeRecipient | Receives the 1% exit fees taken in tokens, through sweepTokenFees |
FeeCollector owner | Change the team's recipient, hand ownership on or renounce it |
FeeCollector team recipient | Receives the team's half of what reaches the collector |
| VOID creator NFT holder | Receives the creator's share of VOID's swap fee on Volta |
What each role can and cannot reach is on Trust model.
| Parameter | Value |
|---|---|
largeExitThreshold | 1,000 HYPE: a HYPE exit paying out more waits 24 hours. Set at deployment, unchanged by the upgrade |
feeCollector | 0x145618DF0662dCd38a2Cf2AC4d24Dfe1FC8A4991 |
tokenFeeRecipient | 0xb06aBb2a232e6e7e91b37ADf79116c41AD4b879a, the fee collector's team recipient, set by the upgrade |
| EIP-712 domain | name voidcash, version 1, chain ID 99901, verifying contract the vault proxy |
paused, entriesPaused | false, 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.
| Token | Address | Decimals | Large-exit threshold | Window cap (per 24 hours) | Listed |
|---|---|---|---|---|---|
| VOID | 0xD31B21Cb80E431AC996269deC31A40fCf048B77f | 18 | 5,000,000 VOID (0.5% of the supply at launch) | 25,000,000 VOID | 2026-11-05, block 1,055,851 |
| VOLTA | 0x0f79931689Af199e7CF868ed1107bBA2C83c68f7 | 18 | 5,000,000 VOLTA (about 0.5% of the supply when listed) | 25,000,000 VOLTA | 2026-11-06, block 1,640,196 |
| BLOB | 0x9a9815Af521149E8D982791703A31bca2F95f534 | 18 | 5,000,000 BLOB (0.5% of the supply) | 25,000,000 BLOB | 2026-11-07, block 2,101,705 |
| YIELDEX | 0x301eB259De132D592966fe0712DB75b27792A68a | 18 | 5,000,000 YIELDEX (about 0.5% of the supply when listed) | 25,000,000 YIELDEX | 2026-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.
| Contract | Address | What it is |
|---|---|---|
| PositionManager | 0x3aB88DDc3CF2A012af88B60828edb4553697E5dC | Volta's Uniswap v4 hook: creates launches and their pools, takes each swap's fee and splits it |
Creator NFT (Flaunch) | 0xac466Ee5CEdD012eB750DBDA0B935F8B997402c7 | One NFT per launch; creates the token. Its holder receives the creator's share |
| FeeEscrow | 0x3D36Beb546E451584736957F97E7EE9D2aCbD9a5 | Holds the creator's and Volta's shares until their owners withdraw them |
| FeeVault | 0xB074897161E8b00d97d3F4163f73de12f7B8f4Ba | Holds each pool's buyback share until Volta's executor spends it |
| Token implementation | 0x541Ef1674D3Cc64D0ab1f14381cA5970FD10B554 | Every launch, VOID included, is a 44-byte clone of it |
| FeeExecutor | 0xD68D650DAFb9BA8517DA430f7f0a94e942E89c41 | Spends the FeeVault on buying VOID back and burning it; only Volta's operators can call it |
| InternalSwapPool | 0x5C1d9b6Dc78CC31A6D08ada1d1c68dA148759c0C | Sells the fees taken in VOID back to later buyers |
VOID's pool, as the fee collector checks it in its constructor:
PoolKey field | Value |
|---|---|
currency0 | 0x0000000000000000000000000000000000000000 (native HYPE) |
currency1 | VOID, 0xD31B21Cb80E431AC996269deC31A40fCf048B77f |
fee | 0: the hook takes the swap fee |
tickSpacing | 60 |
hooks | Volta's PositionManager, 0x3aB88DDc3CF2A012af88B60828edb4553697E5dC |
| Pool id | 0xe488e93cba1cbbb1493d898a4f352571d0d96ddc4902f5449d07ad33ee34ee08 |
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
| Contract | Address |
|---|---|
Uniswap v4 PoolManager (Elysium's, where Volta's pools live) | 0xE2e105d3F7209A9DA11f83cCf3E7398a753823F1 |
ERC-4337 EntryPoint v0.8 | 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108 |
| CreateX | 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 |
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.
| Field | Value |
|---|---|
| Endpoint | https://bundler.voidcash.io (JSON-RPC over POST at / or /rpc; GET /health) |
| EntryPoint | v0.8, 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108 |
| Methods | eth_chainId, eth_supportedEntryPoints, eth_estimateUserOperationGas, eth_sendUserOperation, eth_getUserOperationReceipt, eth_getUserOperationByHash, pimlico_getUserOperationGasPrice, pimlico_getUserOperationStatus |
| Accepted operations | Sender is the vault; no factory, no paymaster, no EIP-7702 authorization |
| Rate limits | 120 requests per minute per client address; 20 per minute for eth_estimateUserOperationGas and eth_sendUserOperation |
| Request size | 64 KB. A vault operation is about 25 KB: its proof is 9,152 bytes |
| Browsers | CORS 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.
| Endpoint | What 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/ready | 200 once the first confirmation is done, 503 before |
GET https://indexer.voidcash.io/health | 200 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 checkThe 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)" $VAULTThe 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) $ACCOUNTThe 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)" 232The 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)" $VAULTHow 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):
| Contract | Block | Date (UTC) |
|---|---|---|
RelationsLib, ZKTranscriptLib | 453473, 453536 | 2026-11-04 |
HonkVerifier (v1, since replaced) | 453654 | 2026-11-04 16:20 |
| Poseidon2 hasher | 454011 | 2026-11-04 |
PrivateVault implementation (v1, since replaced) | 454334 | 2026-11-04 |
PrivateVault proxy | 454409 | 2026-11-04 16:22 |
| VOID, on Volta | launch 232 | 2026-11-04 |
FeeCollector | 528076 | 2026-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:
| Step | Transaction | Block | Result |
|---|---|---|---|
DeployVerifier.s.sol: the v2 HonkVerifier | 0xd69e85b0…d420 | 1,054,961 | 0x29688590CA80928f8f0039334D9f723180cd482a |
UpgradeV2.s.sol: Poseidon2Hash4 | 0x88cf45ff…b9cc | 1,055,394 | 0xdf0EDcbbBBdd91ec58a7dBbc2b7457d553Aa2bc0 |
| The v2 implementation | 0xebdaefaf…246a | 1,055,530 | 0x45648A8aE69C2c4EAE0dc5727E66F8921F771181 |
upgradeToAndCall(implementation, "") | 0xeccfe4d2…fd0a | 1,055,593 | The proxy runs v2 (Upgraded) |
setTokenFeeRecipient | 0x6dd5aa88…ba24 | 1,055,713 | The team's recipient receives token exit fees |
listToken(VOID, 5,000,000 VOID, 25,000,000 VOID) | 0xb1b0f211…a422 | 1,055,851 | VOID 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.
VOID and Volta
VOID for technical readers: its launch on Volta and its Uniswap v4 pool against native HYPE, Volta's 1% swap fee and its buyback, the fee collector's buy-and-burn with its limits, VOID as the vault's first listed token, how the burned total is computed, and the keeper.
Contracts
Every external function, event, struct and error of PrivateVault and FeeCollector, with the Volta trading code and the interfaces they use.