Severity: High Β· Area: Frontend (frontend/src/config/env.ts, frontend/src/config/stellar.ts, frontend/src/context/NetworkContext.tsx)
Description
The app ships a runtime network switcher. NetworkProvider persists the selected network in localStorage under stellarforge_network (NetworkContext.tsx:8, :49-52) and NetworkSwitcher.tsx exposes it in the UI. But the contract identity is not per-network:
// config/env.ts:5-6
factoryContractId: import.meta.env.VITE_FACTORY_CONTRACT_ID ?? '',
tokenWasmHash: import.meta.env.VITE_TOKEN_WASM_HASH ?? '',
// config/stellar.ts:43-48 β one contract id, spread alongside every network's config
export const STELLAR_CONFIG = {
network: resolvedNetwork,
factoryContractId: ENV.factoryContractId,
tokenWasmHash: ENV.tokenWasmHash,
...NETWORK_CONFIGS,
}
NETWORK_CONFIGS (stellar.ts:12-27) correctly varies passphrase, Horizon URL, and RPC URL per network. The factory contract ID and token WASM hash do not vary at all. Switching a testnet-configured build to mainnet keeps sending the testnet contract ID to mainnet RPC. The benign outcome is a confusing "contract not found". The dangerous outcome is that an unrelated contract happens to occupy that ID on mainnet, and the user is prompted to sign a real-XLM transaction against it β the switcher gives no indication that anything is wrong, because from the app's point of view nothing is.
Two compounding problems in the same area:
- Mainnet is broken at the transport layer regardless.
sorobanRpcUrl: 'https://soroban-mainnet.stellar.org' (stellar.ts:21) is hardcoded, and SDF operates no public mainnet Soroban RPC at that address. Mainnet mode cannot work as shipped even with a correct contract ID.
- Caches are keyed on the shared ID.
useTokens.ts:44 and :54 build cache keys as ${network}:${factoryContractId}:β¦. Including the network keeps entries from colliding outright, but the ID component is constant across networks, so the key carries no information about which contract the cached rows came from.
Tasks
Acceptance Criteria
Re-verified on 2026-08-19 during the 30-issue codebase audit tracked in ISSUES.md.
Severity: High Β· Area: Frontend (
frontend/src/config/env.ts,frontend/src/config/stellar.ts,frontend/src/context/NetworkContext.tsx)Description
The app ships a runtime network switcher.
NetworkProviderpersists the selected network inlocalStorageunderstellarforge_network(NetworkContext.tsx:8,:49-52) andNetworkSwitcher.tsxexposes it in the UI. But the contract identity is not per-network:NETWORK_CONFIGS(stellar.ts:12-27) correctly varies passphrase, Horizon URL, and RPC URL per network. The factory contract ID and token WASM hash do not vary at all. Switching a testnet-configured build to mainnet keeps sending the testnet contract ID to mainnet RPC. The benign outcome is a confusing "contract not found". The dangerous outcome is that an unrelated contract happens to occupy that ID on mainnet, and the user is prompted to sign a real-XLM transaction against it β the switcher gives no indication that anything is wrong, because from the app's point of view nothing is.Two compounding problems in the same area:
sorobanRpcUrl: 'https://soroban-mainnet.stellar.org'(stellar.ts:21) is hardcoded, and SDF operates no public mainnet Soroban RPC at that address. Mainnet mode cannot work as shipped even with a correct contract ID.useTokens.ts:44and:54build cache keys as${network}:${factoryContractId}:β¦. Including the network keeps entries from colliding outright, but the ID component is constant across networks, so the key carries no information about which contract the cached rows came from.Tasks
VITE_FACTORY_CONTRACT_ID_TESTNET/_MAINNET, and the same for the WASM hash), resolved throughNETWORK_CONFIGSso a network and its contract identity are always read together and cannot be mismatched by construction.VITE_SOROBAN_RPC_URL_MAINNET) with provider guidance in the docs, and surface an unreachable endpoint rather than failing silently.useTokenscache on the resolved per-network contract ID..env.example,vercel.jsonenv documentation, the README, and the Vercel deploy-button parameters.Acceptance Criteria
Re-verified on 2026-08-19 during the 30-issue codebase audit tracked in
ISSUES.md.