Every wallet and every deploy tool we used quoted a gas price for a fee market that barely exists on Gnosis Chain. We spent months paying that quote at face value — until a redeploy of this protocol's entire 9-contract suite to the Chiado testnet cost less than a thousandth of a US cent, on purpose, using two flags and one small object literal.
Why the default quote is almost always wrong here
Since EIP-1559, every transaction on an EVM chain pays two components: a base fee, set algorithmically by the protocol based on how full recent blocks were, and a priority fee(a tip), which you choose to help a block builder pick your transaction over someone else's when blocks are competitive. Wallets and CLI tools estimate both by looking at recent blocks and padding upward — a sane default for a chain where blocks are routinely full and users are bidding against each other.
Gnosis Chain, and especially its Chiado testnet, is not that chain. Blocks are rarely, if ever, full. There is no real bidding war for block space. The “recent blocks” an estimator samples are mostly empty, but the padding logic still multiplies whatever tiny base fee it finds by a safety factor built for a busier network — so you end up being quoted something like 10 gwei when the chain would have happily included your transaction at 0.01 gwei, a thousand times less.
What this actually cost us
On 2026-07-06 we redeployed this protocol's full contract graph — IntegrityBond, ListingManager, DeveloperPool, SettlementConditions, SpectralMarket, Settlement, DisputeManager, SharedIB, and EvidenceRegistry, 9 contracts and roughly 9.4 million gas total — to Chiado for 0.00000000945 ETH. At the wallet-suggested price for that same gas amount, it would have cost roughly a thousand times more — still cheap in absolute terms, but needlessly so, and enough to matter when your test wallet never holds more than a fraction of a xDAI.
The two places this shows up
You'll hit this default-overquote problem in two distinct places, and the fix looks slightly different in each:
- Deploying or broadcasting with Foundry — every
forge script --broadcastcall estimates a gas price unless told otherwise. - Sending a transaction from a dApp — every
writeContractcall (via wagmi/viem, or any EIP-1559-aware library) lets the connected wallet fall back to its own default estimate unless you pass explicit fee fields.
Foundry: two flags at broadcast time
Foundry's forge script accepts two flags that override its own gas price estimation entirely. Both take a value in wei:
forge script script/Deploy.s.sol:DeployScript \
--rpc-url chiado \
--account your-keystore-account \
--broadcast \
--with-gas-price 10000000 \
--priority-gas-price 1000--with-gas-price sets the max fee per gas (10,000,000 wei = 0.01 gwei here); --priority-gas-pricesets the tip (1,000 wei — effectively negligible, since there is no competing bidder to out-tip). Both flags apply to every transaction in the script's broadcast, no matter how many contracts it deploys.
wagmi/viem: an explicit fee object on every write
The same idea applies inside a dApp. useWriteContract's call accepts maxFeePerGas and maxPriorityFeePerGas directly alongside the usual address/abi/functionNamefields — skip them and the connected wallet falls back to its own (usually padded) estimate instead.
export const LOW_GAS_FEES = {
maxFeePerGas: BigInt(10_000_000), // 0.01 gwei
maxPriorityFeePerGas: BigInt(1_000), // ~0 gwei
} as const;writeContract({
address: addresses.disputeManager,
abi: disputeManagerAbi,
functionName: "mutualClose",
args: [listingId, slotIndex, verdict],
chainId: ACTIVE_CHAIN.id,
...LOW_GAS_FEES,
});Defining the pair once and spreading it into every call site means a single constant governs every transaction the app ever sends — and it's the difference between a user paying what the wallet suggests (often 10–1000× more than necessary) and paying what the chain actually needs.
Finding your own floor instead of copying ours
The exact numbers above are what worked on Chiado on the date we wrote this. They are not universal constants — base fees drift, and a busier chain (including Gnosis mainnet, which carries real economic activity and a real fee market) can behave very differently. Before trusting a hardcoded floor, check the chain yourself:
- Query the current base fee directly against the RPC endpoint you intend to use — a plain
eth_gasPricecall, or read a recent block'sbaseFeePerGas, gives you a live floor rather than a guess. - Set your max fee to a small multiple of that (2–5× is generous headroom on a quiet chain) rather than an arbitrary round number.
- Send one low-stakes transaction first and confirm it actually confirms within a block or two before relying on the same price for anything bigger.
What happens if you go too low
The real failure mode
Push the max fee belowthe chain's actual current base fee and the transaction doesn't fail loudly — it simply sits in the mempool, unconfirmed, because no block builder can include it without violating the protocol's own base-fee rule. It isn't gone; it's stuck, and it will typically keep blocking that account's next nonce until it's replaced.
The fix is the standard EIP-1559 replace-by-fee move: resend a transaction with the same nonceand a higher max fee. Most wallets expose a “speed up” action that does exactly this; from Foundry, rerunning the broadcast with a higher --with-gas-price against the same nonce works the same way.
This is also why testing your floor with one small transaction first (previous section) matters more than the exact numbers — a stuck transaction costs you time and a confusing debugging session, never funds, but it's still worth avoiding.
Quick reference
| Context | How to set it | What we used on Chiado |
|---|---|---|
| Foundry broadcast | --with-gas-price / --priority-gas-price (wei) | 10000000 / 1000 |
| wagmi writeContract | maxFeePerGas / maxPriorityFeePerGas (BigInt wei) | 10_000_000n / 1_000n |
| Sanity check first | eth_gasPrice or a recent block's baseFeePerGas | re-check per chain, per day |
None of this changes what a transaction does — only what it costs to get included. On a chain as quiet as Chiado, that gap between “quoted” and “actually required” is routinely three orders of magnitude, and it compounds fast across a protocol that deploys many contracts and expects users to sign many small transactions.