Guide Developer Tools 6 min read

Floating point breaks ether amounts at the last wei

Ether is counted in whole wei, 10^18 of them to the ether, and converting a decimal amount through ordinary floating point can land a wei or more off. Gas prices in gwei come through the same arithmetic intact when the result is rounded.

Kenji Tanaka
Developer Tools & Cloud Analyst
Published 5 Nov 2026, 11:17 PM (SGT)
Share:
A silver Ethereum coin stacked between other cryptocurrency coins on a black background. A silver Ethereum coin stacked between other cryptocurrency coins on a black background. Photo by WorldSpectrum on Pixabay
Advertisement

Ether, the currency of Ethereum, is counted in wei, and every amount the protocol handles is a whole number of them: one ether is 10^18 wei, and one gwei, the unit gas prices are quoted in, is 10^9 wei. Ordinary floating point gets that whole number wrong more often than it looks. We converted every ether amount from 0.001 to 9.999, in steps of 0.001, and 1,038 of the 9,999 came out the wrong number of wei. Exactly half were too high. Gas prices in gwei, put through the same arithmetic and rounded, came out right 999,999 times out of 999,999.

Unit names splinter across six sources

The Yellow Paper, Ethereum's original formal specification, says "One Ether is defined as being 10^18 Wei", and its current Shanghai text tabulates five names: wei, gwei, szabo, finney and ether. ethereum.org's "Technical intro to ether" keeps two rows, wei and gwei, and its "Gas and fees" page says wei is named after Wei Dai, creator of b-money.

ethers v6 lists seven lowercase names in its units file, and its lookup is case-sensitive, so "Gwei" is an invalid unit there. viem's public constants know three, while its internal table carries the Yellow Paper's five. The web3.js 4.x unit map has 27 keys, among them case variants, aliases such as babbage and shannon, and a "tether" of 10^30 wei that shares its name with an unrelated token. The archived Homestead documentation says some names "bear the family name of seminal figures", without saying whose.

The beacon chain counts differently again. Its specification calls Gwei "the smallest unit of Ether on the beacon chain", and EIP-4895 withdrawals arrive in Gwei and must be converted to wei.

Ordinary ether decimals crack at the wei level

We took the obvious shortcut, Math.round(parseFloat(s) * 1e18), and checked every amount in each set against exact integer arithmetic.

Ether amounts tested (all of them)CountWrong by at least one wei
One decimal, 0.1–99.999980 (8.0%)
Two decimals, 0.01–9.99999104 (10.4%)
Three decimals, 0.001–9.9999,9991,038 (10.4%)
Six decimals, 0.000001–0.0090079,007633 (7.0%)

The largest miss in the three-decimal set was 1,024 wei. The ethers.js v4 documentation had already warned that a Number has holes in its integers past 9,007,199,254,740,991, "only around 0.009 ether (in wei)". That figure is theirs, and marks where a Number stops holding every whole count of wei. It is no safe zone: the last row sits entirely below it and still fails one time in fourteen, and 0.009 ether itself comes out one wei short. The fault is the decimal fraction, which binary cannot hold exactly, carried up by the factor of 10^18. Our guide to IPv6 prefixes and number limits covers the 53-bit limit itself.

Tidy amounts are no safer. 0.1 came through exact, but 1.1 ether is held as 1,100,000,000,000,000,128 wei and printed by JavaScript as 1100000000000000100, wrong in storage and on screen by different amounts.

Gas prices in gwei hold up under rounding

We ran every three-decimal gwei price from 0.001 to 999.999 through the same multiplication, by 10^9 this time, and rounded. All 999,999 matched the exact answer, and 100,000 random prices at the full nine decimals did too. Replace the rounding with Math.floor and 17,516 of the 999,999 came out wrong, 1.75%, each exactly one wei short.

Our reading of why: below about 10^12 wei, neighbouring doubles sit no more than about a ten-thousandth of a wei apart, so rounding removes the float's error, while truncation keeps it whenever the product lands a hair under the integer. Near 10^18 the neighbours are 128 wei apart, beyond any rounding rule's reach.

Advertisement

Sub-wei input splits the libraries apart

Ask for less than one wei and three JavaScript libraries give three answers. We ran each as its published package (ethers 6.17.0, viem 2.57.16, web3-utils 4.3.3). ethers asserts "too many decimals for format", and viem's source says it rounds half away from zero.

Inputethers v6viemweb3.js 4.x
0.5 weithrows1empty string
1.5 weithrows21
1.0000000000000000005 etherthrows10000000000000000011000000000000000000

Our ETH unit converter takes the ethers line and refuses all three. Type 0.5 into its wei row and it answers that the amount is finer than one wei. Until 5 November 2026 it read "1.500" as one and a half without comment, although Unicode's CLDR data writes 1,234.5 as "1.234,5" for Indonesian and Vietnamese, so a reader there could mean fifteen hundred. It also accepted any amount of gas, and a price or fee that would not parse left a bare dash. The revision of that date says how each amount was read and names each error, and it refuses gas above the protocol cap.

Fee rules in EIP-1559 stay whole in wei

EIP-1559, Final and activated in the London upgrade on 5 August 2021, never uses the word "gwei". Every fee in it is a bare integer, and a transaction's fee caps must sit below 2**256. Its starting base fee is written as 1000000000, which is 1 gwei. "The base fee per gas is burned."

The sender pays the base fee plus a capped priority fee: min(max_priority_fee_per_gas, max_fee_per_gas - base_fee_per_gas). Written before the Merge, the EIP gives the tip to a miner; ethereum.org now says validator. Its "Gas and fees" page works a plain transfer as 21,000 × (10 + 2) = 252,000 gwei, or 0.000252 ETH, of which the 0.00021 ETH base fee is burned. On our arithmetic that is 252,000,000,000,000 wei, an integer held exactly.

Transfer gas sits firm at 21,000 under the current fork

The Yellow Paper's G_transaction is 21000, "Paid for every transaction", and the Osaka rules in the execution specifications keep TX_BASE there. That fork, live since 05:49 SGT on 4 December 2025 as the Fusaka upgrade, also added a ceiling: under EIP-7825 no single transaction may use more than 16,777,216 gas. The Prague rules before it set no such cap.

EIP-2780 would break the flat charge into parts. As of 5 November 2026 it is in Last Call, past its 1 November deadline, and the Glamsterdam meta-EIP, EIP-7773, still in Review, lists it as scheduled for inclusion. Its table keeps a transfer to an existing account at 21,000; a transfer to yourself would cost less, and one that creates an account would add state gas. No mainnet date is set.

The Yellow Paper gives out at Cancun

The Yellow Paper's repository keeps a branch per fork, and in every fork branch before Shanghai, Frontier to Paris, the unit table lists four names, with Gwei nowhere. It arrived in commit 8455623, "Shanghai Update (#906)", on 3 July 2024, in the patch that brought withdrawals denominated in Gwei. The repository's branch notes say that text applies to blocks 17,034,870 until 19,426,586, where Cancun took over. A cancun branch has begun, and by February 2025 held one of that upgrade's changes, EIP-1153's transient storage; the README still says the paper does not yet contain the changes Cancun introduced.

From Cancun on, the rules live in the execution specifications and the EIPs. A converter built from the Yellow Paper alone would still count wei correctly, and would know nothing of a gas ceiling in force since December 2025.

Advertisement
Kenji Tanaka
Developer Tools & Cloud Analyst

Kenji Tanaka covers developer tools, cloud platforms, DevOps, CI/CD, and software supply-chain topics for RECATOOLS.

View author profile → · Editorial policy

About this byline Kenji Tanaka is a RECATOOLS editorial persona for developer tools, cloud, DevOps, and software supply-chain coverage. Articles are produced and reviewed under RECATOOLS editorial supervision.

Corrections policy

Advertisement