How to Deploy a Smart Contract on LitVM
A step-by-step developer guide to configuring Foundry and Hardhat, funding testnet wallets, and deploying EVM contracts to LitVM LiteForge.
Updated
To deploy a smart contract on LitVM, configure Foundry or Hardhat to point to the LitVM LiteForge RPC endpoint (https://liteforge.rpc.caldera.xyz/http) using chain ID 4441, and fund your deployer address with testnet zkLTC from the faucet. Because LitVM is fully EVM-equivalent, standard Solidity contracts compiled for Ethereum deploy without code changes. For a high-level architectural overview before deploying, consult Building on LitVM.
LitVM operates as a hybrid rollup rather than a pure zkRollup, combining Arbitrum Nitro execution with Succinct SP1 zero-knowledge proofs. Note that LiteForge is an active testnet and mainnet has not yet launched. Furthermore, the $LITVM token does not exist as a tradeable asset, and gas fees on LiteForge are paid exclusively in testnet zkLTC.
1. Network Configuration
Configure your development environment using the official LiteForge network parameters listed below:
| Parameter | Value |
|---|---|
| Network Name | LitVM LiteForge |
| Chain ID | 4441 |
| RPC URL (HTTP) | https://liteforge.rpc.caldera.xyz/http |
| RPC URL (WebSocket) | wss://liteforge.rpc.caldera.xyz/ws |
| Block Explorer | https://liteforge.explorer.caldera.xyz |
| Faucet | https://liteforge.hub.caldera.xyz |
| Gas Token | zkLTC |
| EVM Version | Shanghai |
2. Wallet Setup and Getting zkLTC
Deploying contracts requires gas paid in zkLTC. On mainnet zkLTC will be LTC bridged in 1:1; on LiteForge it is a free testnet token from the faucet.
- Use an isolated, testnet-only private key. Never use a key that holds real mainnet assets.
- Obtain testnet zkLTC by navigating to the LitVM Testnet Hub at
testnet.litvm.comand selecting "Get zkLTC", or visithttps://liteforge.hub.caldera.xyzdirectly. - Note that the Caldera faucet rate-limits VPN and proxy traffic.
For additional wallet connection options, see the LiteForge testnet guide.
3. The Example Contract
Both paths below deploy the same contract, taken from the LitVM docs. Save it as src/Counter.sol for Foundry or contracts/Counter.sol for Hardhat. The templates that forge init and npx hardhat init generate are different contracts, so replace them, or the count() calls further down will fail.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract Counter {
uint256 public count;
event CountChanged(uint256 newCount);
function increment() public {
count += 1;
emit CountChanged(count);
}
function decrement() public {
require(count > 0, "Count cannot go below zero");
count -= 1;
emit CountChanged(count);
}
function setCount(uint256 _count) public {
count = _count;
emit CountChanged(count);
}
}
LiteForge runs the Shanghai EVM version, which is why the docs pin Solidity 0.8.19. If you compile with a newer compiler, set the target explicitly — evm_version = "shanghai" in foundry.toml, or settings: { evmVersion: "shanghai" } in the Hardhat solidity block — because recent compilers default to later EVM versions whose opcodes Shanghai does not have.
4. Deploying with Foundry
Foundry provides fast, scriptable compilation and deployment.
Installation and Project Setup
Install Foundry and initialize a new project:
curl -L https://foundry.paradigm.xyz | bash
foundryup
forge init my-litvm-project
cd my-litvm-project
Configuration
Update your foundry.toml file to target Solidity 0.8.19 and define the RPC endpoint:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.19"
[rpc_endpoints]
litvm_testnet = "https://liteforge.rpc.caldera.xyz/http"
Create a .env file in your project root to hold your testnet environment variables. Ensure .env is listed in your .gitignore:
PRIVATE_KEY=0x_your_testnet_private_key_here
LITVM_RPC_URL=https://liteforge.rpc.caldera.xyz/http
Load the variables into your shell:
source .env
Build and Test
Compile your contracts and verify test execution:
forge build
forge test
Deployment Script
Create a deployment script at script/Deploy.s.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import "../src/Counter.sol";
contract DeployCounter is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
new Counter();
vm.stopBroadcast();
}
}
Run the deployment script via broadcast:
forge script script/Deploy.s.sol:DeployCounter --rpc-url $LITVM_RPC_URL --broadcast
Alternatively, deploy with a single command. Since Foundry 1.0, forge create only simulates unless you pass --broadcast:
forge create --rpc-url $LITVM_RPC_URL --private-key $PRIVATE_KEY --broadcast src/Counter.sol:Counter
Contract Interaction
Query and write to your deployed contract using cast:
cast call <ADDRESS> "count()" --rpc-url $LITVM_RPC_URL
cast send <ADDRESS> "increment()" --rpc-url $LITVM_RPC_URL --private-key $PRIVATE_KEY
5. Deploying with Hardhat
Hardhat runs in a Node.js (v18+) environment. The LitVM docs are written for Hardhat 2, while a plain npm install hardhat now installs Hardhat 3, which uses npx hardhat --init and a different config format. To follow this guide as written, install the Hardhat 2 line through its hh2 npm tag, as below.
Project Setup
Initialize a project and install dependencies:
npm init -y
npm install --save-dev hardhat@hh2
npx hardhat init
npm install --save-dev @nomicfoundation/hardhat-toolbox@hh2 dotenv
Configuration
Define the LitVM LiteForge network and block explorer settings in hardhat.config.js:
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();
const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
module.exports = {
solidity: "0.8.19",
networks: {
litvm_testnet: {
url: "https://liteforge.rpc.caldera.xyz/http",
chainId: 4441,
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
},
},
etherscan: {
// Blockscout ignores the key, but the verify plugin wants a value.
apiKey: { litvm_testnet: "blockscout" },
customChains: [
{
network: "litvm_testnet",
chainId: 4441,
urls: {
apiURL: "https://liteforge.explorer.caldera.xyz/api",
browserURL: "https://liteforge.explorer.caldera.xyz",
},
},
],
},
};
Deployment Script
Write a deployment script in scripts/deploy.js:
const hre = require("hardhat");
async function main() {
const Counter = await hre.ethers.getContractFactory("Counter");
const counter = await Counter.deploy();
await counter.waitForDeployment();
console.log(`Counter deployed to: ${await counter.getAddress()}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Compile and run the deployment against LiteForge:
npx hardhat compile
npx hardhat run scripts/deploy.js --network litvm_testnet
6. Verifying Your Contract
Verifying your contract source code allows others to inspect and interact with it on the block explorer.
Verifying via Foundry
The LiteForge explorer runs Blockscout, so Foundry's built-in Blockscout verifier needs no API key. The command in the LitVM docs passes an --explorer-api-key flag that current Foundry releases do not have; this form uses the documented options instead.
forge verify-contract --chain 4441 --compiler-version v0.8.19 --watch \n --verifier blockscout \n --verifier-url https://liteforge.explorer.caldera.xyz/api/ \n <ADDRESS> src/Counter.sol:Counter
Verifying via Hardhat
npx hardhat verify --network litvm_testnet <ADDRESS>
7. EVM Behavioral Differences (Arbitrum Orbit)
Because LitVM uses Arbitrum Nitro for optimistic execution under the hood, several EVM properties differ from standard Ethereum L1.
| Feature | Standard Ethereum L1 | LitVM (Arbitrum Nitro) |
|---|---|---|
block.number |
Current Ethereum block number | Approximate Ethereum L1 block number. Use ArbSys(address(100)).arbBlockNumber() for the LitVM block. |
block.timestamp |
Ethereum consensus timestamp | Sequencer clock timestamp. |
| Block Time | Fixed ~12 second intervals | Produced on demand (161ms average block time as of 15 August 2026). Do not rely on block intervals for timing. |
block.difficulty / prevrandao |
Randomness beacon value | Always returns the constant 1. Use an oracle for randomness. |
blockhash() |
Returns past 256 block hashes | Insecure randomness source. Do not use for security-sensitive logic. |
| Block Gas Limit | The real per-block limit | Reads as 1,125,899,906,842,624. Effective execution limit is capped at 32M gas per block; read gasUsed. |
| Gas Estimation | Execution gas only | eth_estimateGas factors in both L2 execution gas and L1 data posting fees. |
msg.sender on L1-to-L2 |
Sender address | Aliased address (L1 address + 0x1111000000000000000000000000000000001111). |
Available Arbitrum precompile addresses include ArbSys (0x64), ArbInfo (0x65), ArbAddressTable (0x66), ArbGasInfo (0x6c), ArbRetryableTx (0x6e), and ArbStatistics (0x6f).
8. Common Deployment Errors
- "Insufficient funds for gas * price + value": Your deployer address has run out of testnet zkLTC. Request additional gas tokens from
https://liteforge.hub.caldera.xyz. - "Nonce too low" / "Nonce too high": Transactions were submitted out of sequence or remain pending in the mempool. Inspect your wallet's current nonce using
cast nonce <ADDRESS> --rpc-url $LITVM_RPC_URLand wait for pending transactions to clear.
Questions
What network parameters are needed to deploy on LitVM testnet?
To deploy on the LitVM LiteForge testnet, set your RPC URL to https://liteforge.rpc.caldera.xyz/http and the Chain ID to 4441. Gas is paid in testnet zkLTC.
How do I get the current LitVM block number in Solidity?
Calling block.number returns the approximate Ethereum L1 block number rather than the LitVM block height. To retrieve the native LitVM block number, call ArbSys(address(100)).arbBlockNumber() using the Arbitrum precompile at address 0x64.
Which development frameworks work with LitVM?
LitVM is fully EVM-equivalent and supports Foundry, Hardhat, Remix, ethers.js, and viem. Contracts compiled for Ethereum deploy unchanged, provided they target the Shanghai EVM version; the docs use Solidity 0.8.19.
Does contract deployment on LitVM require $LITVM tokens?
No. LitVM uses zkLTC (backed 1:1 by LTC) as its base gas token. The $LITVM governance token does not exist as a tradeable asset yet, and LiteForge is an active testnet.