Skip to content
LitVMSwapDocs
Open app
Developers / Network setup
Developers

Network setup

LitVMSwap lives on LitVM. Here's everything you need to point your wallet, script or app at the right chain.

The basics

SettingValue
Network nameLitVM LiteForge
Chain id4441 (hex 0x1159)
Gas tokenzkLTC, 18 decimals
RPChttps://liteforge.rpc.caldera.xyz/http
Explorerliteforge.explorer.caldera.xyz
Multicall30xcA11bde05977b3631167028862bE2a173976CA11
Block timeFast. Roughly 4 blocks per second

Testing in a browser? This button asks your wallet to add the network (nothing gets signed):

viem

TypeScript
import { defineChain } from 'viem'

export const litvm = defineChain({
  id: 4441,
  name: 'LitVM LiteForge',
  nativeCurrency: { name: 'zkLTC', symbol: 'zkLTC', decimals: 18 },
  rpcUrls: { default: { http: ['https://liteforge.rpc.caldera.xyz/http'] } },
  blockExplorers: {
    default: { name: 'LiteForge Explorer', url: 'https://liteforge.explorer.caldera.xyz' },
  },
  contracts: {
    multicall3: { address: '0xcA11bde05977b3631167028862bE2a173976CA11' },
  },
})

wagmi

TypeScript
import { createConfig, http } from 'wagmi'
import { litvm } from './litvm'

export const config = createConfig({
  chains: [litvm],
  transports: { [litvm.id]: http() },
})

ethers v6

TypeScript
import { JsonRpcProvider } from 'ethers'

export const provider = new JsonRpcProvider('https://liteforge.rpc.caldera.xyz/http', {
  chainId: 4441,
  name: 'litvm',
})

Adding the network by hand

Some wallets want the details typed in. Use the values from the table above, or call wallet_addEthereumChain yourself:

TypeScript
await window.ethereum.request({
  method: 'wallet_addEthereumChain',
  params: [
    {
      chainId: '0x1159',
      chainName: 'LitVM LiteForge',
      nativeCurrency: { name: 'zkLTC', symbol: 'zkLTC', decimals: 18 },
      rpcUrls: ['https://liteforge.rpc.caldera.xyz/http'],
      blockExplorerUrls: ['https://liteforge.explorer.caldera.xyz'],
    },
  ],
})

Gotchas worth knowing

Native zkLTC vs wzkLTC

zkLTC pays for gas, like ETH on Ethereum. Pools can't hold native coins, so they hold wzkLTC at 0x315374AA9b5536037Cc1Efeea2439CCC0913A77e, a standard wrapper with deposit() and withdraw(uint256).

When you talk to the APIs, use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE to mean native zkLTC. When you talk to the pools directly, use the wzkLTC address.

block.number inside contracts

LitVM is an Arbitrum-style chain. Inside a contract, block.number gives you the parent chain's block number, not LitVM's. The number your RPC, explorer and eth_getLogs use comes from the ArbSys precompile:

Solidity
interface ArbSys {
    function arbBlockNumber() external view returns (uint256);
}

function litvmBlock() view returns (uint256) {
    // ArbSys lives at address 0x64 on Arbitrum-style chains
    return ArbSys(address(0x64)).arbBlockNumber();
}

If you store a block number on chain so you can look up logs later, store this one. block.timestamp is fine as is. Heads up: a local fork (anvil and friends) usually won't show the difference, so test on the real chain too.

Blocks are quick

About 4 blocks a second means around 345,000 blocks a day. That matters when you call eth_getLogs: ask for ranges of a few thousand blocks at a time instead of "everything since launch". There's a ready helper on Events and indexing.

Decimals

Read decimals() from every token you touch. On LitVM, ZKUSDC uses 18 decimals, not 6.