# Contract Deployment Runbook **Last Updated:** 2026-02-12 **Full deployment order:** For the canonical sequence (prerequisites → core → PMM/pools → provider → optional → cW* → verification) and remaining recommendations, see [DEPLOYMENT_ORDER_OF_OPERATIONS.md](DEPLOYMENT_ORDER_OF_OPERATIONS.md). **Deployment safety:** Use **RPC_URL_138** (Core only, from `smom-dbis-138/.env`) for all deployments; never use Public RPC. All secrets from **`smom-dbis-138/.env`** only. Run a gas/cost estimate before deploy (e.g. `cd smom-dbis-138 && ./scripts/deployment/calculate-costs-consolidated.sh`). **Do not deploy when transactions are stuck** — clear tx pool (`./scripts/clear-all-transaction-pools.sh`), wait ~60s, then retry; use scripts that check nonce when available. ## Chain 138 deployment requirements (learned 2026-02-12) - **Gas price:** Chain 138 enforces a minimum gas price. Always use **`--with-gas-price 1000000000`** (1 gwei) for `forge script` and `forge create` when deploying to Chain 138; otherwise transactions fail with "Gas price below configured minimum gas price". - **Gas 32xxx when deploying:** If you see gas-related RPC errors (e.g. -32000, execution reverted, or out of gas), add **`--gas-estimate-multiplier 150`** (or 200) to `forge script ... --broadcast` so the broadcast uses a higher gas limit. See [RPC_ERRORS_32001_32602.md](../09-troubleshooting/RPC_ERRORS_32001_32602.md). - **On-chain check:** After deployments, run `./scripts/verify/check-contracts-on-chain-138.sh` (uses `RPC_URL_138`; optional URL arg). Address list comes from `config/smart-contracts-master.json` when available. See [CONTRACT_ADDRESSES_REFERENCE](../11-references/CONTRACT_ADDRESSES_REFERENCE.md), [ADDRESS_MATRIX_AND_STATUS](../11-references/ADDRESS_MATRIX_AND_STATUS.md). - **TransactionMirror:** The deploy script can hit a Forge broadcast constructor-args decode error. If so, deploy manually: `forge create contracts/mirror/TransactionMirror.sol:TransactionMirror --constructor-args --rpc-url $RPC_URL_138 --private-key $PRIVATE_KEY --gas-price 1000000000`. ## RPC Routing Summary Chain 138 uses two standard env vars: **RPC_URL_138** (Core, admin/deploy) and **RPC_URL_138_PUBLIC** (Public, bridge/frontend). See [RPC_ENDPOINTS_MASTER](../04-configuration/RPC_ENDPOINTS_MASTER.md). | Use Case | VMID | IP | Ports | Variable | |----------|------|-----|-------|----------| | Admin / contract deployment | 2101 | 192.168.11.211 | 8545, 8546 | RPC_URL_138 (Core) | | Bridge, monitoring, public-facing | 2201 | 192.168.11.221 **(FIXED)** | 8545, 8546 | RPC_URL_138_PUBLIC (Public) | ## Prerequisites 1. **.env check (keys only, no secrets printed):** From repo root: `./scripts/deployment/preflight-chain138-deploy.sh` (RPC, dotenv, nonce). Or from smom-dbis-138: `./scripts/deployment/check-env-required.sh` — verifies `PRIVATE_KEY`, `RPC_URL`, `RPC_URL_138` and optional PMM/mainnet/CCIP vars. Use **`smom-dbis-138/.env`** only for deploy secrets. 2. **Network access** to Chain 138 RPC (set `RPC_URL_138` in .env, e.g. http://192.168.11.211:8545 for Core) - Run from a host on the same LAN as Proxmox, or via VPN - WSL/remote dev environments may get "No route to host" if not on network 3. **PRIVATE_KEY** in `smom-dbis-138/.env` (deployer wallet with gas; same wallet holds LINK for bridge fees) 4. **Foundry** (`forge`) installed 5. **Test all contracts before deploy (Phase 0.8):** Run `./scripts/deployment/test-all-contracts-before-deploy.sh` from repo root. This runs `forge build` and `forge test` in smom-dbis-138. Use `--dry-run` to print commands only; `--alltra` to include alltra-lifi-settlement; `--no-match "Fork|Mainnet|Integration|e2e"` for unit tests only. See [DEPLOYMENT_ORDER_OF_OPERATIONS](DEPLOYMENT_ORDER_OF_OPERATIONS.md) § Phase 0.8. ### Deprecated bridge (R4) Do not use CCIPWETH9Bridge at `0x89dd...`. Use only the canonical bridge at `0x971c...` and set `CCIPWETH9_BRIDGE_CHAIN138` in env. See docs/00-meta/RECOMMENDATIONS_OPERATOR_CHECKLIST.md R4. ### Env required per deploy script | Script / phase | Required env | Notes | |----------------|--------------|--------| | DeployMulticall, DeployOracle, DeployMultiSig | `PRIVATE_KEY`, `RPC_URL_138` (Chain 138 Core) | deploy-all-contracts.sh | | 01_DeployCore, 02_DeployBridges | `PRIVATE_KEY`, RPC; 02 needs `UNIVERSAL_ASSET_REGISTRY`, `GOVERNANCE_CONTROLLER` | Phased core | | DeployCCIPReceiver, DeployCCIPSender | `PRIVATE_KEY`, `CCIP_ROUTER_ADDRESS`, `ORACLE_AGGREGATOR_ADDRESS`; Sender optional: `LINK_TOKEN_ADDRESS` | Set in .env; see .env.example | | DeployWETHBridges (mainnet receiver) | `MAINNET_WETH9_BRIDGE_ADDRESS`, `MAINNET_WETH10_BRIDGE_ADDRESS` when configuring cross-chain | .env.example | | DeploySmartAccountsKit | `PRIVATE_KEY`, `RPC_URL_138`; optional `ENTRY_POINT`, `SMART_ACCOUNT_FACTORY`, `PAYMASTER` if pre-deployed | Script does not deploy contracts; obtain EntryPoint/Factory from MetaMask kit or ERC-4337 impl and set in env | | DeployTransactionMirror | `PRIVATE_KEY`, `MIRROR_ADMIN` (optional, default deployer) | If `forge script` fails with constructor-args decode, use forge create — see § TransactionMirror below | | DeployReserveSystem | `TOKEN_FACTORY` in .env | Phase 6 | ## Deploy Core Contracts (Chain 138) ```bash cd smom-dbis-138 source .env # Verify RPC: curl -s -X POST "$RPC_URL" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' bash scripts/deployment/deploy-all-contracts.sh ``` Deploys: Multicall, Oracle, MultiSig (WETH9/10 pre-deployed in genesis). ## Deploy Unified (Ordered or Parallel) ```bash cd smom-dbis-138 ./scripts/deployment/deploy-contracts-unified.sh --mode ordered # or ./scripts/deployment/deploy-contracts-unified.sh --mode parallel ``` ## Deploy WETH Bridges (CCIP) ```bash # From project root (use GAS_PRICE=1000000000 if min-gas-price error) GAS_PRICE=1000000000 ./scripts/deploy-and-configure-weth9-bridge-chain138.sh # Then set CCIPWETH9_BRIDGE_CHAIN138 in smom-dbis-138/.env ``` ## Smart accounts (ERC-4337) **Script:** `smom-dbis-138/script/smart-accounts/DeploySmartAccountsKit.s.sol` (and `DeployAccountWalletRegistryExtended.s.sol` for registry). **Required env (in `smom-dbis-138/.env`):** `PRIVATE_KEY`, `RPC_URL_138` (Chain 138 Core). Optional: set `ENTRY_POINT`, `SMART_ACCOUNT_FACTORY`, `PAYMASTER` if already deployed; otherwise the script will deploy and log addresses to set in `.env`. **Deploy (Chain 138):** ```bash cd smom-dbis-138 source .env forge script script/smart-accounts/DeploySmartAccountsKit.s.sol --rpc-url $RPC_URL_138 --broadcast --with-gas-price 1000000000 # Set ENTRY_POINT, SMART_ACCOUNT_FACTORY, PAYMASTER from output ``` **Verification:** Run script; confirm logged addresses match env. See [PLACEHOLDERS_AND_TBD](../PLACEHOLDERS_AND_TBD.md) Smart Accounts Kit. ## TransactionMirror (Chain 138) **Script:** `script/DeployTransactionMirror.s.sol`. **Deployed address:** Set in `smom-dbis-138/.env` as `TRANSACTION_MIRROR_ADDRESS` from the script output (e.g. past deploys: `0xE362aa10D3Af1A16880A799b78D18F923403B55a`, `0x4eeF36BBaf706C6da5859cF9B34E9934fEC3E006`). **Recommended:** Use the combined script; it **always checks nonce**, **validates RPC is active (chainId 138)**, uses **proper gas** (1 gwei min), and loads the **correct dotenv** (`smom-dbis-138/.env` + `config/ip-addresses.conf` for RPC fallbacks). **Required in `smom-dbis-138/.env`:** `PRIVATE_KEY`, `RPC_URL_138` (Core RPC, 192.168.11.211:8545). No Public fallback for deployments. Optional: `GAS_PRICE` or `GAS_PRICE_138` (default 1000000000). Before deploying: if Core was read-only, run `./scripts/maintenance/make-rpc-vmids-writable-via-ssh.sh` then `./scripts/maintenance/health-check-rpc-2101.sh`. See [RPC_2101_READONLY_FIX.md](RPC_2101_READONLY_FIX.md). **If you see "Known transaction" or "Replacement transaction underpriced":** Clear the tx pool then retry: `./scripts/clear-all-transaction-pools.sh` (or RPC-only; see script). Run from a host that can reach `RPC_URL_138` (same LAN/VPN): ```bash ./scripts/deployment/deploy-transaction-mirror-and-pmm-pool-after-txpool-clear.sh ``` This deploys TransactionMirror and creates the DODO cUSDT/cUSDC PMM pool, then runs on-chain verification. **Core RPC only** (no Public fallback). If Core is unreachable, fix read-only and health first (see RPC_2101_READONLY_FIX.md). Options: `--dry-run` (env, RPC, nonce only); `--force` (skip RPC check). **Skip stuck nonce manually:** Set `NEXT_NONCE` to the next nonce (e.g. `13370`) so the script uses `vm.setNonce` and deploys at a new address; then set `TRANSACTION_MIRROR_ADDRESS` in `.env` to the logged address. The combined script already sets `NEXT_NONCE` from pending nonce. Or run the two forge commands manually (ensure RPC is Chain 138 and nonce is correct): ```bash cd smom-dbis-138 && source .env # Optional: export NEXT_NONCE= if avoiding a stuck tx forge script script/DeployTransactionMirror.s.sol:DeployTransactionMirror --rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price 1000000000 forge script script/dex/CreateCUSDTCUSDCPool.s.sol:CreateCUSDTCUSDCPool --rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price 1000000000 ``` If `forge script` fails with "Failed to decode constructor arguments", deploy via `forge create`: ```bash cd smom-dbis-138 source .env ADMIN="${MIRROR_ADMIN:-$(cast wallet address --private-key $PRIVATE_KEY)}" forge create contracts/mirror/TransactionMirror.sol:TransactionMirror \ --constructor-args "$ADMIN" \ --rpc-url "$RPC_URL_138" \ --private-key "$PRIVATE_KEY" \ --legacy \ --gas-price 1000000000 ``` Or run the helper script (from repo root, **from a host on LAN** that can reach `RPC_URL_138` e.g. 192.168.11.211:8545): `./scripts/deployment/deploy-transaction-mirror-chain138.sh`. The script exports `ETH_RPC_URL` so Forge uses the correct RPC and, on success, updates or appends `TRANSACTION_MIRROR_ADDRESS` in `smom-dbis-138/.env`. ## AlltraAdapter — setBridgeFee after deploy After deploying or using AlltraAdapter (138 ↔ ALL Mainnet 651940), set the bridge fee to match ALL Mainnet fee structure. **Required:** `ALLTRA_ADAPTER_CHAIN138` in `smom-dbis-138/.env` (adapter address; see config/smart-contracts-master.json). Optional: `ALLTRA_BRIDGE_FEE` (wei) to pass to setBridgeFee. Deployer must have `DEFAULT_ADMIN_ROLE`. ```bash cd smom-dbis-138 && source .env # Use ALLTRA_BRIDGE_FEE from .env if set, else 0.001 ALL (1000000000000000 wei) FEE="${ALLTRA_BRIDGE_FEE:-1000000000000000}" cast send "$ALLTRA_ADAPTER_CHAIN138" "setBridgeFee(uint256)" "$FEE" \ --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --gas-price 1000000000 ``` Document the final fee in [PLACEHOLDERS_AND_TBD](../PLACEHOLDERS_AND_TBD.md) § AlltraAdapter when known. ## Vault ac* / vdc* / sdc* (Chain 138) After deploying the Vault System (`DeployVaultSystem.s.sol`), run the single script that creates all asset/deposit (ac*) and debt (vdc*) tokens via `VaultFactory.createVaultWithDecimals`. **Required env:** `VAULT_FACTORY_ADDRESS`, `PRIVATE_KEY`, `RPC_URL_138`. Optional: `OWNER`, `ENTITY` (default deployer); `CUSDC_ADDRESS_138`, `CUSDT_ADDRESS_138` or `COMPLIANT_USDC_ADDRESS`, `COMPLIANT_USDT_ADDRESS` (skip currency if unset). Option A — deploy Vault System then ac/vdc/sdc in one go: run `./scripts/deployment/deploy-vault-system-and-ac-vdc-sdc.sh` from `smom-dbis-138` (uses `PRIVATE_KEY`, `RPC_URL_138`; parses VaultFactory from broadcast and runs ac/vdc/sdc step). Option B — run steps separately: ```bash cd smom-dbis-138 source .env forge script script/deploy/vault/DeployVaultSystem.s.sol:DeployVaultSystem \ --rpc-url "$RPC_URL_138" --broadcast --with-gas-price 1000000000 # From output, set VAULT_FACTORY_ADDRESS=0x... then: forge script script/deploy/vault/DeployAcVdcSdcVaults.s.sol:DeployAcVdcSdcVaults \ --rpc-url "$RPC_URL_138" --broadcast --with-gas-price 1000000000 ``` Deployer must have `VAULT_DEPLOYER_ROLE` on VaultFactory. Each configured base token gets one vault with deposit token (ac*) and debt token (vdc*), 6 decimals, transferable debt. See [MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT](../runbooks/MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md). Full architecture and phased roadmap: see [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md). ## EnhancedSwapRouter & DODOPMMProvider (post-deploy configuration) When Uniswap V3, Balancer, or DODO PMM pools exist on Chain 138 / 651940, configure the router and provider so on-chain quotes and swaps work. **EnhancedSwapRouter** (set by address with `ROUTING_MANAGER_ROLE`): | Config | Method | Env (optional) | When | |--------|--------|----------------|------| | Uniswap V3 Quoter | `setUniswapQuoter(address)` | `ENHANCED_SWAP_ROUTER_UNISWAP_QUOTER` | After Uniswap Quoter is deployed on chain | | Balancer pool (WETH↔stable) | `setBalancerPoolId(tokenIn, tokenOut, poolId)` | `BALANCER_WETH_USDC_POOL_ID`, `BALANCER_WETH_USDT_POOL_ID` | After Balancer pool exists | | Dodoex pool | `setDodoPoolAddress(tokenIn, tokenOut, pool)` | Set via cast or script when DODO pool is known | After DODO PMM pool deployed | Example (Chain 138, after setting env): ```bash cd smom-dbis-138 && source .env # Uniswap Quoter [ -n "$ENHANCED_SWAP_ROUTER_UNISWAP_QUOTER" ] && cast send "$ENHANCED_SWAP_ROUTER" "setUniswapQuoter(address)" "$ENHANCED_SWAP_ROUTER_UNISWAP_QUOTER" --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --gas-price 1000000000 # Balancer (bytes32 pool IDs; use cast send with 0x-prefixed hex) # cast send "$ENHANCED_SWAP_ROUTER" "setBalancerPoolId(address,address,bytes32)" "$BALANCER_WETH_USDC_POOL_ID" ... ``` **DODOPMMProvider:** Register existing DODO PMM pools so `getQuote` / `executeSwap` work. Address with `POOL_MANAGER_ROLE` calls `registerPool(tokenIn, tokenOut, pool)`. ```bash # After DODO pool is deployed (e.g. cUSDT↔USDT) cast send "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "" "" "" --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --gas-price 1000000000 ``` Optional .env placeholders (see `smom-dbis-138/.env.example`): `ENHANCED_SWAP_ROUTER_UNISWAP_QUOTER`, `BALANCER_WETH_USDC_POOL_ID`, `BALANCER_WETH_USDT_POOL_ID`, `DODO_PMM_PROVIDER_ADDRESS`. Until set, router returns 0 for Uniswap/Balancer quotes and DODO provider returns no pool. ## Private stabilization pools (Master Plan Phase 2) XAU-anchored private pools (cUSDT↔XAU, cUSDC↔XAU, cEURT↔XAU) for the Stabilizer; only the Stabilizer or whitelisted keeper should execute swaps. See [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md) §5. **Script:** `smom-dbis-138/script/dex/DeployPrivatePoolRegistryAndPools.s.sol` — deploys [PrivatePoolRegistry](../../smom-dbis-138/contracts/dex/PrivatePoolRegistry.sol) and optionally creates pools via [DODOPMMIntegration](../../smom-dbis-138/contracts/dex/DODOPMMIntegration.sol) `createPool`, then registers them in the registry. **Env (in `smom-dbis-138/.env`):** | Variable | Description | |----------|--------------| | `PRIVATE_KEY` | Deployer (must have `POOL_MANAGER_ROLE` on DODOPMMIntegration to create pools) | | `PRIVATE_POOL_REGISTRY_ADMIN` | Admin for PrivatePoolRegistry (default: deployer) | | `DODOPMM_INTEGRATION_ADDRESS` | Deployed DODOPMMIntegration (set to create XAU pools in same run) | | `XAU_ADDRESS_138` | XAU token address on Chain 138 (required to create XAU-anchored pools) | | `COMPLIANT_USDT_ADDRESS` | cUSDT on Chain 138 | | `COMPLIANT_USDC_ADDRESS` | cUSDC on Chain 138 | | `cEURT_ADDRESS_138` | cEURT on Chain 138 (optional; omit to skip cEURT↔XAU pool) | **Deploy:** ```bash cd smom-dbis-138 && source .env forge script script/dex/DeployPrivatePoolRegistryAndPools.s.sol:DeployPrivatePoolRegistryAndPools \ --rpc-url "$RPC_URL_138" --broadcast --with-gas-price 1000000000 ``` If only the registry is needed (pools created later), leave `DODOPMM_INTEGRATION_ADDRESS` or `XAU_ADDRESS_138` unset. To register existing pools manually: `cast send "$PRIVATE_POOL_REGISTRY" "register(address,address,address)" ...`. Grant `STABILIZER_LP_ROLE` to allowed LPs when using a wrapper that checks it. ## Stabilizer deployment and configuration (Phase 3 + 6) Deploy the [Stabilizer](../../smom-dbis-138/contracts/bridge/trustless/integration/Stabilizer.sol) (Master Plan Phase 3) after PrivatePoolRegistry and private XAU-anchored pools exist. The Stabilizer calls `checkDeviation()` (peg manager or TWAP) and `executePrivateSwap(tradeSize, tokenIn, tokenOut)` via the private pool registry. Phase 6: TWAP/sustained N-block deviation, per-block volume cap, flash drain recovery target <3 blocks (see [OPERATIONS_RUNBOOK](../../smom-dbis-138/docs/OPERATIONS_RUNBOOK.md) Flash Loan Containment). **Deploy (e.g. via forge create or a small script):** - Constructor: `(admin, privatePoolRegistryAddress)`. - Set in `.env`: `STABILIZER_ADDRESS`, `PRIVATE_POOL_REGISTRY_ADDRESS`, `STABLECOIN_PEG_MANAGER_ADDRESS` (or commodity peg), peg asset address. **Configuration (admin):** | Parameter | Method | Typical / notes | |-----------|--------|------------------| | Peg source | `setStablecoinPegSource(manager, asset)` or `setCommodityPegSource(manager, asset)` | One of them; deviation from peg used for `checkDeviation()` | | thresholdBps | `setThresholdBps(uint256)` | e.g. 50 (0.5%) | | minBlocksBetweenExecution | `setMinBlocksBetweenExecution(uint256)` | e.g. 3–5 (block delay) | | maxStabilizationVolumePerBlock | `setMaxStabilizationVolumePerBlock(uint256)` | Cap per block | | maxSlippageBps | `setMaxSlippageBps(uint256)` | e.g. 100 (1%) | | maxGasPriceForStabilizer | `setMaxGasPriceForStabilizer(uint256)` | MEV resistance; 0 = disabled | | sustainedDeviationBlocks | `setSustainedDeviationBlocks(uint256)` | N blocks over threshold before rebalance (Phase 6) | **Keeper:** Grant `STABILIZER_KEEPER_ROLE` to the keeper EOA or bot: `cast send "$STABILIZER_ADDRESS" "grantRole(bytes32,address)" $(cast keccak "STABILIZER_KEEPER_ROLE()") "$KEEPER_ADDRESS" --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --gas-price 1000000000` **Operational target (Phase 6):** Flash drain recovery <3 blocks. The contract enforces sustained deviation over N blocks, per-block volume cap, and block delay; document in [OPERATIONS_RUNBOOK](../../smom-dbis-138/docs/OPERATIONS_RUNBOOK.md) and [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md) §8/§16. ## Contract Verification (Blockscout) Use the **Forge Verification Proxy** for `forge verify-contract` (Blockscout expects `module`/`action` in query; Forge sends JSON only). The verification script uses **canonical addresses** from `smom-dbis-138/.env` and `config/ip-addresses.conf` (ORACLE_PROXY, AGGREGATOR_ADDRESS, CCIP_SENDER, CCIPWETH9_BRIDGE_CHAIN138, etc.); run from a host on LAN that can reach Blockscout (192.168.11.140:4000). **Preferred: orchestrated script (starts proxy if needed, timeout 900s default):** ```bash source smom-dbis-138/.env 2>/dev/null ./scripts/verify/run-contract-verification-with-proxy.sh ``` **Manual (proxy + verify):** ```bash # 1. Start proxy (in separate terminal) BLOCKSCOUT_URL=http://192.168.11.140:4000 node forge-verification-proxy/server.js # 2. Run verification ./scripts/verify-contracts-blockscout.sh ``` **See:** [forge-verification-proxy/README.md](../../forge-verification-proxy/README.md), [BLOCKSCOUT_FORGE_VERIFICATION_EVALUATION.md](BLOCKSCOUT_FORGE_VERIFICATION_EVALUATION.md). Fallback: manual verification at https://explorer.d-bis.org/address/#verify-contract **Runbooks in sync (R12):** [BLOCKSCOUT_FIX_RUNBOOK](BLOCKSCOUT_FIX_RUNBOOK.md), [BLOCKSCOUT_FORGE_VERIFICATION_EVALUATION](BLOCKSCOUT_FORGE_VERIFICATION_EVALUATION.md), this runbook. **Full recommendations (R1–R24):** [RECOMMENDATIONS_OPERATOR_CHECKLIST](../00-meta/RECOMMENDATIONS_OPERATOR_CHECKLIST.md). --- ## Troubleshooting | Error | Cause | Fix | |-------|-------|-----| | `No route to host` | Dev machine cannot reach RPC (RPC_URL_138, e.g. 192.168.11.211:8545) | Run from machine on LAN or VPN; or set RPC_URL_138=https://rpc-core.d-bis.org | | `PRIVATE_KEY not set` | Missing in .env | Add deployer key to smom-dbis-138/.env | | `Gas price below configured minimum gas price` | Chain 138 minimum gas not met | Use `--with-gas-price 1000000000` for all `forge script` / `forge create` on Chain 138 | | RPC -32xxx / out of gas when deploying | Gas estimate too low or estimation failed | Use `--gas-estimate-multiplier 150` (or 200) with `forge script ... --broadcast`; ensure deployer has enough ETH. See [RPC_ERRORS_32001_32602.md](../09-troubleshooting/RPC_ERRORS_32001_32602.md). | | `Failed to decode constructor arguments` (TransactionMirror) | Forge broadcast decode bug | Deploy via `forge create ... --constructor-args --gas-price 1000000000` | | `pam_chauthtok failed` (Blockscout) | Container PAM restriction | Use Proxmox Web UI: Container 5000 → Options → Password | | `pvesm not found` (verify-storage) | Script must run ON Proxmox host | `ssh root@r630-01` then run script |