Skip to main content

Deployment

This guide covers deploying all three layers of ZibaXeer: smart contracts to HyperPaxeer, the backend API to Railway, and the frontend to Vercel.

Smart Contracts

Prerequisites

  • Foundry installed (forge, cast, anvil)
  • A funded deployer wallet on HyperPaxeer
  • DEPLOYER_PRIVATE_KEY set in your environment

Deploy to HyperPaxeer Mainnet

cd contracts

# Deploy all contracts via the deployment script
forge script script/Deploy.s.sol \
  --rpc-url https://public-mainnet.rpcpaxeer.online/evm \
  --private-key $DEPLOYER_PRIVATE_KEY \
  --broadcast \
  --verify

Verify on PaxScan

forge verify-contract <CONTRACT_ADDRESS> src/core/VaultFactory.sol:VaultFactory \
  --chain-id 125 \
  --etherscan-api-key $PAXSCAN_API_KEY \
  --rpc-url https://public-mainnet.rpcpaxeer.online/evm

Deployment Order

Deploy contracts in this order to satisfy dependencies:
1

ArgusOracle

No dependencies. Deploy first.
2

RiskManager

Requires: ArgusOracle address as constructor argument.
3

VaultRegistry

No dependencies beyond initial owner address.
4

RevenueSplitter

Requires: treasury, leaderShareBps, protocolFeeBps as constructor arguments.
5

PaxDexAdapter

Requires: paxDexRouter address as constructor argument.
6

CopyTradingVault (implementation)

Deploy the implementation contract only. Do not call initialize — the proxy constructor handles that.
7

VaultFactory

Requires: VaultRegistry, RiskManager, and CopyTradingVault implementation address.After deployment run:
  • VaultRegistry.setAuthorizedFactory(VaultFactory address)
  • VaultFactory.initialize(owner, implAddress, registryAddress, riskManagerAddress)

Post-Deploy Configuration

# Set the authorized factory on the registry
cast send $VAULT_REGISTRY_ADDRESS "setAuthorizedFactory(address)" $VAULT_FACTORY_ADDRESS \
  --rpc-url https://public-mainnet.rpcpaxeer.online/evm \
  --private-key $DEPLOYER_PRIVATE_KEY

Backend

Railway

  1. Connect your GitHub repository to Railway
  2. Create a new project → Deploy from GitHub
  3. Select apps/backend as the root directory
  4. Set environment variables:
DATABASE_URL=postgresql://...
REDIS_URL=redis://...
PORT=4000
  1. Railway auto-detects Node.js and runs pnpm start

Database Migration (Production)

cd packages/db
DATABASE_URL=postgresql://... pnpm prisma migrate deploy

Docker (Alternative)

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install -g pnpm && pnpm install --frozen-lockfile
CMD ["pnpm", "--filter", "@zibaxeer/backend", "start"]

Indexer

The indexer is a long-running process. Deploy it alongside the backend:
# On your server or Railway service
cd apps/indexer
pnpm start
Required environment variables:
RPC_URL=https://public-mainnet.rpcpaxeer.online/evm
VAULT_FACTORY_ADDRESS=0x...      # Deployed VaultFactory address
KNOWN_VAULT_ADDRESSES=0x...,...  # Any vaults deployed before this indexer run
REDIS_URL=redis://...            # Same Redis as backend

Frontend

Vercel

cd apps/frontend
vercel deploy --prod
Or connect via the Vercel dashboard → Import Git Repository → set root directory to apps/frontend. Set environment variables in the Vercel dashboard:
NEXT_PUBLIC_RPC_URL=https://public-mainnet.rpcpaxeer.online/evm
NEXT_PUBLIC_CHAIN_ID=125
NEXT_PUBLIC_EXPLORER_URL=https://paxscan.paxeer.app
NEXT_PUBLIC_API_URL=https://api.zibaxeer.io

Infrastructure Checklist

Before going live, verify every item:
All contracts deployed and verified on PaxScan
VaultRegistry.authorizedFactory set to VaultFactory address
ArgusOracle pointing to live Paxeer Argus endpoint
PostgreSQL database migrated with latest schema
Redis instance running and accessible to both backend and indexer
VAULT_FACTORY_ADDRESS set in indexer environment
Backend /health returns 200 OK
Frontend NEXT_PUBLIC_API_URL pointing to live backend
CORS configured in backend to allow frontend domain

Upgrading Contracts

All core contracts use UUPS — upgrades go through a governance tx:
# Deploy new implementation
forge script script/Upgrade.s.sol \
  --rpc-url https://public-mainnet.rpcpaxeer.online/evm \
  --broadcast

# Call upgradeToAndCall on the proxy
cast send $PROXY_ADDRESS "upgradeToAndCall(address,bytes)" \
  $NEW_IMPLEMENTATION_ADDRESS \
  0x \
  --rpc-url https://public-mainnet.rpcpaxeer.online/evm \
  --private-key $DEPLOYER_PRIVATE_KEY
Production upgrades should always go through a multi-sig (e.g. Gnosis Safe). Never upgrade directly from a single EOA in production.