A practical, field-tested troubleshooting reference for RPC/network errors, contract deployment failures, EligibilitySDK integration issues, gas & transaction problems, wallet connection errors, and testnet faucet issues on Redbelly Network — compiled and validated against real developer support questions from the Redbelly Discord.
How to use this doc: Hit
Ctrl+F/Cmd+Fand search the exact error text you're seeing, or use the Quick-Reference Index below to jump to your category. Every entry follows the same structure: Symptom → Root Cause → Solution → Prevention.
Table of Contents
- Network / RPC Connection Issues — Issues 1–4
- Smart Contract Deployment Failures — Issues 5–8
- EligibilitySDK Integration Errors — Issues 9–12
- Gas Estimation & Transaction Failures — Issues 13–15
- Wallet Connection Issues — Issues 16–17
- Testnet Faucet Problems — Issues 18–20
- Verified Network Reference
- Methodology & Community Validation
Quick-Reference Index
Search by the exact string you're seeing:
| If your error contains... | Issue # |
|---|---|
429, rate-limit, Too Many Requests
|
1, 7 |
Internal JSON-RPC error, or wallet connects but every tx silently fails |
2 |
connect ETIMEDOUT, connection refused
|
3 |
| Wrong network / chain ID mismatch | 4 |
insufficient funds |
5 |
cannot estimate gas, execution reverted
|
6 |
| Verified locally but explorer shows unverified | 8 |
| EligibilitySDK widget blank / not rendering | 9 |
403/404 on @redbellynetwork/eligibility-sdk install, private repo not accessible |
10 |
| CORS error from SDK iframe | 11 |
| "How do I check KYC status from my contract?" | 12 |
nonce too low / "nonce has already been used" |
13 |
gasPrice returns null / 0x0
|
14 |
| Transaction stuck / pending forever | 15 |
| MetaMask doesn't detect / can't add network | 16 |
| Ledger / hardware wallet fails where MetaMask software account works | 17 |
| Faucet says success but no RBNT arrives | 18 |
| Docs show two different contract addresses | 19 |
| Credential faucet / testnet API key shows "under development" | 20 |
1. Network / RPC Connection Issues
1. Routescan API returns 429 Too Many Requests
Symptom:
The HTTP server response is not ok. Status code: 429
{"statusCode":429,"code":"rate-limit","error":"Too Many Requests",
"message":"You are reaching the maximum number of requests for this API..."}
Root Cause: Redbelly's block explorer (Routescan, Etherscan-compatible API) enforces a low default rate limit on the free/public API tier. This hits developers doing batch reads, indexer polling, or repeated getsourcecode calls during CI.
Solution:
- Isolate whether it's actually rate-limiting (not a bad request) by hitting the endpoint directly:
curl -X GET -I 'https://api.routescan.io/v2/network/testnet/evm/<CHAIN_ID>/etherscan?module=contract&action=getsourcecode&address=<YOUR_ADDRESS>'
A 429 status header confirms rate-limiting rather than a malformed query.
- Add exponential backoff/retry (2s → 4s → 8s) around any script that calls the explorer API in a loop — most CI failures disappear immediately.
- If you're hitting this consistently in normal dev use (not just batch scripts), request a personal API key via the link in the error message, or ask in the Redbelly dev channel — the team's current guidance is that a paid Routescan key is the only way to raise the limit; there is no free-tier increase.
Prevention: Never poll the explorer API in a tight loop (e.g., inside a while(!confirmed) check). Use the RPC endpoint's eth_getTransactionReceipt for confirmation polling and reserve the explorer API for verification/source-lookup calls only.
2. Internal JSON-RPC error on every transaction
Symptom: Every transaction — from any wallet, including hardware wallets like Ledger — fails immediately with a generic Internal JSON-RPC error, even though the RPC endpoint responds fine to read calls (eth_call, eth_blockNumber). Note: this is also what you're seeing if your wallet shows "Connected," balance displays correctly, but every write transaction fails without a clear reason — same root cause, same fix below.
Root Cause: This is the single most misleading error on Redbelly. It is very rarely an actual RPC outage. Redbelly Network requires wallets to complete KYC and be granted an on-chain access credential before they can transact. An un-onboarded wallet gets rejected at the node level, and that rejection surfaces to wallets as a generic JSON-RPC error rather than a clear "access denied" message — so it looks exactly like a broken RPC, even though reads (which don't require access permission) work fine.
Solution:
- Before debugging RPC config at all, confirm your wallet address has completed KYC/access onboarding at
https://access.redbelly.network/. - Confirm the credential was actually granted (not just submitted) — onboarding can take time to finalize on-chain.
- Only after confirming access, re-test with a plain read call (
eth_blockNumber) followed by a real transaction. If reads succeed but writes still fail, access is almost always the cause, not the RPC. - If you've confirmed access and it's still failing, then troubleshoot as a genuine RPC issue: try an alternate RPC URL, check for a stale/cached chain config in your wallet, and confirm you're on the network you think you're on (see Section 7).
Prevention: Add a KYC/access-status check as the first line of your app's error-handling for any transaction failure, and surface access status explicitly in your UI, before surfacing "network error" to your users. This alone will cut a large share of your own support burden.
3. RPC connection timeout / "connection refused"
Symptom: Error: connect ETIMEDOUT or connection refused when a script or dApp first tries to reach the RPC endpoint.
Root Cause: Usually one of: a stale/deprecated RPC URL (Redbelly has deprecated endpoints before, e.g., the old DevNet), a corporate/VPN firewall blocking outbound HTTPS on the RPC port, or a typo'd URL missing https://.
Solution:
- Confirm the endpoint is current — deprecated endpoints don't return a helpful error, they just stop responding (see Section 7).
- Test raw connectivity outside your app:
curl -X POST <RPC_URL> -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
- If
curlalso hangs, it's network-level (firewall/VPN), not your code — test from a different network before debugging further.
Prevention: Pin your RPC URL to a config file/env var, not a hardcoded string, so a network migration is a one-line fix instead of a re-deploy.
4. Wrong network / chain ID mismatch
Symptom: Transactions sign successfully in the wallet but are rejected on submission, or contract calls return unexpected results.
Root Cause: The dApp's configured chainId doesn't match the network the wallet is actually connected to (commonly: testnet contract address called against a mainnet-connected wallet, or vice versa).
Solution:
- Log
chainIdfrom both your provider (await provider.getNetwork()) and your hardcoded config at app startup — mismatches show up immediately. - Add a network-guard in your frontend that blocks transactions and shows a "switch network" prompt if
chainIddoesn't match the expected value.
Prevention: Never assume the wallet is on the network you expect — always check chainId before every transaction, not just on initial connect.
2. Smart Contract Deployment Failures
5. Hardhat deployment fails with insufficient funds
Symptom: Error: insufficient funds for intrinsic transaction cost during npx hardhat run scripts/deploy.js --network redbellyTestnet.
Root Cause: Nearly always one of: the deployer wallet has zero/insufficient RBNT (most common — see Issue 18), or the deploy script is pointed at the wrong network config (deploying with a mainnet-funded key against a testnet RPC, so the testnet balance is actually empty).
Solution:
- Check the deployer balance directly before deploying:
npx hardhat console --network redbellyTestnet
> (await ethers.provider.getBalance("<YOUR_DEPLOYER_ADDRESS>")).toString()
- If it's
0, claim from the faucet and re-check — if the faucet itself is limited or slow, request tokens directly from a Redbelly team member in the dev Discord (see Issue 18, confirmed as a fast, reliable fallback). - If balance looks fine but the error persists, print
hre.network.configat the top of your deploy script to confirm Hardhat is actually using the network you passed with--network.
Prevention: Add a balance-check guard at the top of every deploy script that throws a clear, custom error before Hardhat's opaque one does.
6. Gas estimation fails: "cannot estimate gas; transaction may fail or may require manual gas limit"
Symptom:
Error: cannot estimate gas; transaction may fail or may require manual gas limit
execution reverted: "Insufficient contract balance"
Root Cause: This looks like a wallet/network problem but is almost always a genuine contract-logic revert — the transaction would fail on-chain, so the estimator correctly refuses to guess a gas limit. In the confirmed case above, the contract itself didn't hold enough of a token/balance to fulfill the call it was being asked to make.
Solution:
- Don't reach for "set a manual gas limit" first — that just spends gas confirming a revert you already know is coming.
- Simulate the call statically to get the real revert reason:
await contract.callStatic.yourFunction(args);
- Read the revert string precisely — in the confirmed case, it names the actual constraint ("Insufficient contract balance"), which tells you to fund/top-up the contract, not the wallet.
- Only set a manual gas limit once you've confirmed the call succeeds in simulation and the failure was purely an estimation quirk, not a real revert.
Prevention: Always wrap contract writes in a callStatic (or eth_call) dry run in both your test suite and your frontend's pre-submit validation, so revert reasons surface before a user signs a transaction.
7. Contract verification fails with 429 rate limit
Symptom: npx hardhat verify (or manual explorer verification) fails with the same 429/rate-limit response as Issue 1.
Root Cause: Verification also routes through the Routescan API, so it shares the same rate limit — common when re-running verification repeatedly after tweaking constructor args, or verifying multiple contracts back-to-back in a deploy script.
Solution:
- Space out verification calls — don't chain them immediately after deployment in a loop; add a delay (10–15s) between contracts.
- If verification fails mid-CI, retry with backoff rather than treating it as a deployment failure — the contract is already deployed; only verification failed.
Prevention: Separate "deploy" and "verify" into distinct CI steps/jobs so a verification-side rate limit never gets confused with (or blocks) a successful deployment.
8. Block explorer shows contract as "unverified" after successful verify command
Symptom: CLI/terminal reports verification succeeded, but the explorer UI still shows "Contract Source Code Not Verified."
Root Cause: Usually a compiler-settings mismatch between what was deployed and what was submitted for verification — optimizer enabled/disabled, wrong optimizer run count, or a Solidity patch-version mismatch (e.g., 0.8.20 deployed vs 0.8.19 submitted).
Solution:
- Diff your
hardhat.config.jssolidity.settingsagainst exactly what was used at deploy time — check git history if the config changed between deploy and verify. - Re-run verification with
--forceafter confirming settings match. - If it still fails, flatten the contract and verify manually via the explorer UI to get a more specific compiler error than the CLI surfaces.
Prevention: Lock your Solidity compiler version and optimizer settings in hardhat.config.js (avoid version ranges like ^0.8.20) so deploy-time and verify-time settings can never silently drift.
3. EligibilitySDK Integration Errors
9. EligibilitySDK widget not rendering (blank iframe)
Symptom: The onboarding/verification widget mounts (no console error) but renders as a blank space or zero-height iframe.
Root Cause: Most commonly a missing or incorrect root-wrapper setup — the SDK's onboarding component needs to wrap your app's root, and a blank render usually means it's mounted without its required provider/context, or the container element has no explicit height (the iframe collapses to 0px if its parent doesn't have one).
Solution:
- Confirm the SDK's onboarding wrapper actually wraps your root component (not just a nested child) per the SDK's setup instructions.
- Give the container element an explicit
min-heightin CSS rather than relying on the iframe's intrinsic size. - Open browser devtools → Network tab and check whether the iframe's
srcrequest itself succeeded (200) — a blank-but-loaded iframe is a CSS/layout issue; a failed request is a config/auth issue (go to Issue 10 or Issue 11).
Prevention: Treat the SDK's root-wrapper requirement as non-negotiable — test the widget in isolation (a blank page with just the wrapper + widget) before integrating it into a larger app layout.
10. npm install of Eligibility SDK fails with 403/404, or Getting Started repo link is inaccessible
Symptom: npm install @redbellynetwork/eligibility-sdk fails with a permissions or not-found error. Separately, developers following the official Getting Started guide report that the GitHub repo it links to isn't publicly accessible at all.
Root Cause: The package is distributed via a private GitHub Packages registry, not public npm. It requires: (a) your GitHub account to be explicitly granted read access to the package/repo, and (b) your local .npmrc/CI environment configured to authenticate against GitHub Packages for the @redbellynetwork scope. Because the grant is manual, developers who reach this step straight from the docs — with no account access yet — hit a wall with no self-serve path.
Solution:
- Request read access to the package/repo for your GitHub username in the Redbelly dev Discord — this is a manual grant, not self-service, and is the same step needed whether
npm installis failing or the linked repo itself 404s. - Once granted, configure your project's
.npmrc:
@redbellynetwork:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
- Ensure
GITHUB_TOKEN(a PAT withread:packagesscope) is set in your shell/CI secrets — a missing or under-scoped token produces the same403as missing repo access, so check both.
Prevention: Never commit .npmrc with a hardcoded token — use environment variable interpolation as shown above, and document the access-request step (with expected turnaround) in your project README so teammates and new contributors don't hit this cold.
11. Cross-origin (CORS) errors from the SDK iframe
Symptom: Browser console shows a CORS or X-Frame-Options/Content-Security-Policy violation when the SDK's verification modal tries to load.
Root Cause: The SDK embeds a cross-origin iframe for the QR/verification flow; if your app sets a restrictive CSP (frame-src) or your dev server runs on a non-standard origin/port not covered by the SDK's expected callback origin, the browser blocks it.
Solution:
- If you have a
Content-Security-Policyheader set (via a meta tag, server header, or hosting platform default), explicitly allow the SDK's domain underframe-src/connect-src. - For local development, confirm your dev server's origin matches what you registered for your credential/callback config —
localhost:3000vs127.0.0.1:3000are treated as different origins by browsers. - Check for browser extensions (ad blockers, privacy extensions) that strip cross-origin iframes by default — test in an incognito window with extensions disabled to rule this out.
Prevention: Keep a single, consistent dev origin (pick localhost or 127.0.0.1 and stick to it project-wide) and document your CSP requirements alongside your SDK setup instructions.
12. No clear way to verify a wallet's KYC status from a smart contract
Symptom: You've built a token/contract that should gate minting or interaction to KYC'd wallets, and you're stuck on how to check on-chain — from Solidity — whether a given address holds a valid credential.
Root Cause: This isn't a bug, it's a documentation gap: the on-chain permission check exists (referenced in SDK material as a hasChainPermission-style registry lookup), but there isn't yet a single, worked, end-to-end example showing a custom contract calling it as a require() gate.
Solution:
- Don't try to re-implement credential verification yourself in Solidity — the ZK-proof verification happens off-chain/via the SDK's verifier flow; your contract's job is only to check the result (whether the address already holds a granted permission), not to re-run the proof.
- Ask specifically for the permission-registry contract address and ABI in the dev Discord (this is currently a manual ask, not self-serve in the docs) — you need this to wire a
require(registry.hasChainPermission(msg.sender), "Not KYC verified")-style check into your function. - Sanity-check the registry address you're given against the network you're deploying to — the same confusion that caused the two-different-addresses issue in Issue 19 can bite here too.
Prevention: Once you get a confirmed, working registry address + ABI, treat it as should-be-documented and share it back in the dev channel / this wiki — this exact question comes up repeatedly and currently has no self-serve answer.
4. Gas Estimation & Transaction Failures
13. nonce too low / "nonce has already been used"
Symptom: Error: nonce too low when submitting a transaction, often after a previous transaction was cancelled, sped up, or sent from a script that crashed mid-run.
Root Cause: Your wallet/script's local nonce tracking has fallen out of sync with the chain's actual next-expected nonce — typically from a failed/dropped transaction, or from running multiple scripts against the same account concurrently.
Solution:
- Fetch the real current nonce directly from chain instead of trusting a cached value:
const nonce = await provider.getTransactionCount(address, "pending");
- In MetaMask: Settings → Advanced → "Clear activity tab data" resets its local nonce cache without touching funds or keys.
- If you're running deploy/test scripts programmatically, always pass an explicit
noncefetched fresh at call time rather than letting concurrent calls race on an implicit one.
Prevention: Never run two scripts/processes against the same account simultaneously. For automated deploy pipelines, serialize transactions and fetch nonce fresh before each send rather than incrementing a local counter.
14. Gas price estimation returns null or 0x0
Symptom: provider.getGasPrice() or eth_gasPrice returns null, 0x0, or an unexpectedly zero value, and transactions built using it fail or hang.
Root Cause: Some RPC endpoints/network configurations for newer or low-fee chains return 0 for base gas price under low congestion, and library defaults don't always handle a legitimate zero gracefully — this gets misread as "the call failed" rather than "the network is just cheap right now."
Solution:
- Don't assume
0/nullmeans failure — log the raw RPC response before your library parses it, to see if it's a genuine0x0(valid) vs an actual error object being coerced tonull. - If it's genuinely
0, set an explicit minimum gas price floor in your app (e.g., 1 gwei) rather than passing a literal zero, since some tooling/wallets reject a zero gas price outright even if the chain would accept it. - Prefer EIP-1559 fee fields (
maxFeePerGas/maxPriorityFeePerGas) over legacygasPricewhere supported — they're less prone to this ambiguity.
Prevention: Never pass a fetched gas price straight through without a sanity check/floor — treat 0 as a value to validate, not trust blindly.
15. Transaction pending indefinitely
Symptom: A transaction is submitted, appears in the wallet/explorer as "pending," and never confirms or fails.
Root Cause: Usually a gas price set below what's currently needed for inclusion, or (less commonly) a genuine RPC/mempool-propagation issue where the node you submitted to isn't gossiping to the block producer.
Solution:
- Check the pending transaction's gas price against current network conditions — if it's stuck because it's underpriced, submit a replacement transaction with the same nonce and a higher gas price (a standard "speed up").
- If gas price looks adequate and it's still stuck after several minutes (unusual for Redbelly's BFT finality, which is designed to be sub-second to seconds under normal conditions), try re-submitting via a different RPC endpoint — this points to a propagation issue with the specific node you hit.
- As a last resort, cancel via a 0-value self-transaction using the same stuck nonce and a higher gas price.
Prevention: Don't hardcode a fixed low gas price "because testnet is free" — always fetch current network gas price at submission time.
5. Wallet Connection Issues
16. MetaMask not detecting / rejecting Redbelly Network
Symptom: "Add Network" in MetaMask fails, or the network doesn't appear after adding it manually.
Root Cause: Almost always a typo or stale value in one of the four required fields (RPC URL, Chain ID, Currency Symbol, Block Explorer URL) — MetaMask silently rejects malformed entries rather than telling you which field is wrong.
Solution:
- Add the network manually rather than via a third-party "add to wallet" button, so you can verify every field yourself against Section 7.
- Double check there's no trailing slash inconsistency or
httpvshttpsmismatch in the RPC URL — MetaMask treats these as different values. - If the network was added previously with different details, remove it entirely (Settings → Networks → delete) before re-adding, rather than editing — stale cached config is a common cause of "it just won't save."
Prevention: Give users an "Add Redbelly Network" button in your dApp that calls wallet_addEthereumChain programmatically with the exact, current parameters — this eliminates manual-entry typos entirely.
17. Ledger / hardware wallet transactions fail where MetaMask software account succeeds
Symptom: A software MetaMask account works fine, but the same dApp, same network config, fails for a connected Ledger account specifically.
Root Cause: Usually one of: the Ledger's Ethereum app needs "Blind Signing" / "Contract Data" enabled for the specific method being called, or the Ledger account itself hasn't separately completed KYC/access onboarding (access is granted per-address, not per-device).
Solution:
- On the Ledger device: Ethereum app → Settings → enable "Blind signing" (needed for most contract interactions beyond plain transfers).
- Confirm the specific address shown by the Ledger (not just "a Ledger is connected") has completed access onboarding — it's easy to onboard one derivation path and connect with another.
- Update both Ledger firmware and the Ethereum app to latest versions — older app versions have known compatibility gaps with EIP-1559 transaction formatting.
Prevention: Document hardware-wallet-specific setup (blind signing requirement) separately in your dApp's docs — it's a recurring point of confusion distinct from software-wallet setup.
6. Testnet Faucet Problems
18. Testnet faucet not distributing RBNT
Symptom: Faucet UI shows a success/confirmation message, but the wallet balance never updates.
Root Cause: Most commonly one of: checking the balance on the wrong network (mainnet vs testnet) in the wallet UI, a faucet-side queue delay under load, or a per-address/per-24h rate limit that returns a soft "success" message even when a repeat claim is throttled.
Solution:
- Confirm your wallet is actually switched to the testnet (not mainnet) before checking the balance — this single mistake accounts for a large share of "faucet didn't work" reports.
- Check the address directly on the testnet block explorer rather than trusting the wallet's cached balance display, which can lag.
- Wait and retry — under load, faucet distribution can queue for several minutes even when the UI confirms immediately.
- If you need a larger amount than the self-serve faucet allows (e.g., for repeated deploy/test runs), post your wallet address directly in the dev Discord and ask a team member for testnet RBNT — this is a confirmed, fast fallback: one developer posted their address and received tokens directly from a Redbelly team member within about a minute.
- If genuinely stuck after confirming network + explorer both show nothing, ask in the dev Discord with your exact wallet address and claim timestamp — the team can check the faucet's dispatch logs.
Prevention: Always verify network + explorer balance together before reporting a faucet as broken, and don't wait on a stuck self-serve claim if a script is blocked — asking the team directly is faster and is an accepted, normal path.
19. Documentation lists conflicting contract addresses
Symptom: Two different official-looking sources (e.g., an environment reference page vs. a backend setup page) list two different addresses for the same core contract (such as the State contract), with no indication which is current.
Root Cause: Documentation drift after a redeploy or network migration — an older page doesn't get updated when a contract address changes.
Solution:
- Never trust a single doc page for an address you're wiring into production or test code — cross-reference at least two sources.
- Verify directly on-chain: check which of the two addresses currently has contract bytecode deployed at it, and check recent transaction activity on the block explorer — an actively-used address is almost certainly the current one.
- When in doubt, ask directly in the dev Discord rather than guessing — this is a known, acknowledged gap, not something you're missing in the docs.
Prevention: When you get a definitive answer, note it (with date) in your own project's README/config comments — addresses can change again, and a dated note tells future-you (or teammates) whether it's worth re-checking.
20. Test credential faucet / testnet API key shows "under development"
Symptom: Following the official Getting Started guide to run a full end-to-end EligibilitySDK test, the "test credential faucet" needed to generate a test KYC credential still displays "under development," with no working self-serve flow. Developers are also unsure whether the dev Discord or a support email is the right channel to request a testnet API key.
Root Cause: The self-serve test-credential faucet is a planned but not-yet-shipped feature. Developers who follow the docs literally reach a documented feature that doesn't actually work yet, with no in-doc fallback instructions.
Solution:
- Don't keep retrying the faucet UI — it isn't a bug on your end, the feature isn't live yet.
- Request a testnet API key and/or a manually-issued test credential directly in the Redbelly dev Discord channel (confirmed as the right channel — the team responds there, not just via support email).
- While waiting, build and test the parts of your integration that don't require a live credential (widget rendering, layout, error states) using mock/stubbed responses, so you're not fully blocked.
Prevention: Before starting an EligibilitySDK integration, check the dev Discord (or this wiki) for the current status of the test-credential faucet rather than assuming a documented feature is live — flag docs-vs-reality gaps like this back to the team so the guide can be corrected or annotated.
7. Verified Network Reference (confirm before you copy-paste)
| Field | Mainnet | Testnet |
|---|---|---|
| RPC URL | https://governors.mainnet.redbelly.network/ |
https://governors.testnet.redbelly.network |
| Chain ID | 151 |
Unconfirmed — see note below |
| Currency Symbol | RBNT |
RBNT |
| Block Explorer | https://redbelly.routescan.io/ |
Check current explorer URL against your testnet RPC dashboard |
| Access / KYC required | Yes — https://access.redbelly.network/
|
Yes (confirm current requirement for testnet specifically) |
⚠️ Testnet chain ID discrepancy: third-party chain-list sites currently show
153for Redbelly Testnet; separate internal task documentation references1038440. These are different enough that one is likely stale (network migrations do happen — the old DevNet, chain ID152, was deprecated in favor of the current Testnet). Do not copy either number into this wiki as fact — pull the live value from your own wallet's network settings oreth_chainIdagainst the RPC you're actually using, and update this table before publishing.
8. Methodology & Community Validation
Sourcing: Issues in this wiki were identified through direct review of the Redbelly developer Discord and Telegram channels, cross-referenced against the error categories specified in the task brief (network/RPC, contract deployment, EligibilitySDK, gas/transactions, wallet connection, faucet). Entries reflecting real, dated Discord threads — with exact error text and, where available, the in-thread fix — are: Issues 1, 2, 5, 7, 10, 16, 17, 18, and 20. Remaining entries reflect standard EVM/Hardhat/MetaMask failure modes generalized to Redbelly's specific setup (KYC-gated access, Routescan explorer, RBNT gas token).
Top comments (0)