Local Development Network
Run a single-node local Monolythium chain for development and testing. A local devnet provides instant block times, zero gas costs, and full control over chain state.
Prerequisites
monodbinary installed (Installation Guide)- Go 1.21+ (if building from source)
- Node.js 18+ (for Hardhat/Foundry frontend tests)
Initialize the Node
# Remove any existing state
rm -rf ~/.mono
# Initialize a fresh local chain
monod init localtest --chain-id mono-local-1
# Create a test key (no password prompt with test backend)
monod keys add devkey --keyring-backend test
Save the mnemonic output from keys add -- you will need it to connect wallets.
Configure Genesis
Fund your development account and tune the chain for fast iteration.
Fund Accounts
# Get your address
DEV_ADDR=$(monod keys show devkey -a --keyring-backend test)
# Add genesis account with 1 billion LYTH
monod genesis add-genesis-account $DEV_ADDR 1000000000000000000000000000alyth
# Create gentx (self-delegate as validator)
monod genesis gentx devkey 100000000000000000000000alyth \
--chain-id mono-local-1 \
--keyring-backend test
# Collect genesis transactions
monod genesis collect-gentxs
Fast Block Configuration
Edit ~/.mono/config/config.toml for near-instant blocks:
[consensus]
timeout_propose = "200ms"
timeout_prevote = "100ms"
timeout_precommit = "100ms"
timeout_commit = "500ms"
Low Gas Prices
Edit ~/.mono/config/app.toml:
# Accept zero-fee transactions for development
minimum-gas-prices = "0alyth"
[json-rpc]
enable = true
address = "0.0.0.0:8545"
ws-address = "0.0.0.0:8546"
api = "eth,net,web3,txpool,debug,personal"
Enable CORS (for Browser dApps)
In ~/.mono/config/config.toml:
[rpc]
cors_allowed_origins = ["*"]
In ~/.mono/config/app.toml:
[api]
enable = true
address = "tcp://0.0.0.0:1317"
enabled-unsafe-cors = true
[grpc]
enable = true
address = "0.0.0.0:9090"
Start the Node
monod start
You should see blocks produced every ~500ms. The following endpoints become available:
| Service | URL |
|---|---|
| EVM JSON-RPC | http://localhost:8545 |
| EVM WebSocket | ws://localhost:8546 |
| Cosmos RPC | http://localhost:26657 |
| REST API | http://localhost:1317 |
| gRPC | localhost:9090 |
Run in the background with output to a log file:
monod start > ~/.mono/devnet.log 2>&1 &
Connecting Hardhat
// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
module.exports = {
solidity: "0.8.24",
networks: {
local: {
url: "http://localhost:8545",
chainId: 262146, // mono-local-1 EVM chain ID (derived from chain-id)
accounts: {
mnemonic: "your devkey mnemonic here",
},
gas: "auto",
gasPrice: "auto",
},
},
};
Deploy contracts:
npx hardhat run scripts/deploy.js --network local
Monolythium targets the paris EVM version. Set this in your Hardhat config:
solidity: {
version: "0.8.24",
settings: { evmVersion: "paris" },
},
Connecting Foundry
# Deploy with Foundry
forge create src/MyContract.sol:MyContract \
--rpc-url http://localhost:8545 \
--private-key $DEVKEY_PRIVATE_KEY \
--legacy \
--gas-limit 3000000
# Run tests against local node
forge test --fork-url http://localhost:8545
Add to foundry.toml:
[profile.default]
evm_version = "paris"
[rpc_endpoints]
local = "http://localhost:8545"
Use the --legacy flag with Foundry. Monolythium uses the feemarket module but local devnets may not have a populated base fee history.
Connecting CosmJS
import { SigningStargateClient, GasPrice } from "@cosmjs/stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(
"your devkey mnemonic here",
{ prefix: "mono" }
);
const client = await SigningStargateClient.connectWithSigner(
"http://localhost:26657",
wallet,
{ gasPrice: GasPrice.fromString("0alyth") }
);
const [account] = await wallet.getAccounts();
const balance = await client.getBalance(account.address, "alyth");
console.log("Balance:", balance);
Docker (Optional)
If you prefer containerized development, use a single-node Docker setup:
docker run -d \
--name mono-local \
-p 8545:8545 \
-p 8546:8546 \
-p 26657:26657 \
-p 1317:1317 \
-p 9090:9090 \
-e CHAIN_ID=mono-local-1 \
-e MINIMUM_GAS_PRICES=0alyth \
ghcr.io/mono-labs-org/monod:latest \
monod start
The Docker image includes a pre-initialized genesis with a funded account. Check the image documentation for the default mnemonic and addresses.
Reset Chain State
To wipe all state and start fresh:
# Stop the node first
monod tendermint unsafe-reset-all
Or remove everything and re-initialize:
rm -rf ~/.mono
# Re-run the initialization steps above
Faucet for Local Development
For local testing, you already have a fully funded genesis account. To fund additional addresses:
monod tx bank send devkey mono1newaddress... 1000000000000000000000alyth \
--chain-id mono-local-1 \
--keyring-backend test \
--gas auto \
--gas-adjustment 1.5 \
--yes
Troubleshooting
Node won't start after genesis changes
Reset state with monod tendermint unsafe-reset-all and reinitialize.
EVM transactions fail with "invalid chain ID"
The EVM chain ID is derived from the Cosmos chain ID. For mono-local-1, use the numeric chain ID returned by eth_chainId.
Blocks aren't being produced
Ensure the gentx was collected (monod genesis collect-gentxs) and the validator has sufficient self-delegation.
MetaMask can't connect
Verify CORS is enabled and the JSON-RPC address binds to 0.0.0.0 (not 127.0.0.1).
Related
- Installation -- Building and installing
monod - Gas & Fee Mechanics -- How gas and fees work on Monolythium
- EVM RPC Endpoints -- Deploying contracts via RPC
- Deploying Contracts -- Hardhat and Foundry deployment guides