Crypto amounts are integers: 1 ETH is 1000000000000000000 wei

A balance of 1 ETH is not 1.0 — it is 1000000000000000000 wei, an exact whole number. Every protocol that matters works this way, and the bugs appear the moment a decimal point gets involved. Why the integer representation exists and what breaks without it.

Ethereum has no fractional amounts. Neither does Bitcoin. What looks like 0.1 ETH in a wallet is stored, transmitted and validated as the integer 100000000000000000, and the decimal point exists only in the interface you are looking at.

This is not a quirk. It is the single design decision that makes the arithmetic sound, and it is why 0.1 + 0.2 not being 0.3 is a problem these systems never have to solve.

The short version

Every amount is a count of the smallest indivisible unit.

Chain Base unit Display unit Factor
Ethereum wei ether 1018
Bitcoin satoshi BTC 108

Every one of those conversions is exact. There is no rounding anywhere, because moving between units is multiplying or dividing by a power of ten and the underlying value is always a whole number of base units.

Why not just use decimals

Because a binary floating-point number cannot represent most decimal fractions. The value 0.1 has no exact representation in a double, so the nearest available value is stored instead. Ask a language for 0.1 + 0.2 and you get 0.30000000000000004 — not a bug, just the nearest double to the real answer.

Now watch what that does when the amount is a balance. Take that stray value and convert it:

0.30000000000000004 ether
 → 300000000000000040 wei

Those extra 40 wei are not a typo. They are the floating-point error, made concrete and now sitting in a transaction. On a single transfer it is meaningless. In a contract that sums thousands of balances and asserts that the total matches, it is a failed invariant. In a system that pays out balance and then checks balance == 0, it is a leak.

The integer representation does not fix floating-point arithmetic. It avoids it entirely. There is no fraction to misrepresent because there is no fraction.

Where the decimal point actually lives

Only in presentation. The rule that keeps this straight:

Parse to integer at the edge, compute in integers, format to decimal at the edge.

Concretely:

  1. A user types 0.05. Convert it to 50000000000000000 wei as a string operation, by shifting the decimal point, never by parseFloat(x) * 1e18.
  2. All arithmetic — adding, comparing, splitting, fee deduction — happens on the integer.
  3. When displaying, insert the decimal point back into the digit string.

Step one is where nearly every bug is born. parseFloat("0.1") * 1e18 gives 100000000000000000 today and something else for a value you have not tested. The multiplication happens in floating point, so it inherits every representation error and then scales it by 1018.

Why gas prices are quoted in gwei

Gas is priced per unit of gas in wei, and a realistic price is around 21000000000 wei. Nobody can read that, so it is quoted in gwei — 109 wei:

21 gwei = 21000000000 wei
        = 0.000000021 ether

Gwei exists purely so a human can compare 21 against 35 instead of counting zeroes. It is a display unit, and the node never sees it.

The mistakes that actually cost money

Multiplying a parsed float by 1018. The canonical bug. Shift the string instead.

Using a 64-bit integer for wei. The maximum safe integer in JavaScript is about 9.007 × 1015 — smaller than one ether, which is 1018. A Number cannot hold a single ETH balance in wei without losing precision. Use BigInt, or a big-decimal library, or a string. This one is silent: it produces plausible numbers that are quietly wrong.

Rounding at an intermediate step. Splitting 1 wei three ways is not 0.333 wei. It is 0 wei with 1 left over, and where that remainder goes is a decision you must make deliberately, not one to paper over.

Assuming 18 decimals. ETH has 18. Most ERC-20 tokens have 18. USDC has 6. WBTC has 8. A hardcoded 1e18 against a 6-decimal token is off by a factor of a trillion, and it will look like a working integration right up until it is not.

Comparing formatted strings. "1.0" and "1.00" are different strings and the same amount. Compare the integers.

What this does not model

The unit converter here handles the two families above — the ether family and the bitcoin family — and it deliberately refuses to convert between them, because there is no exchange rate in a unit conversion and pretending otherwise would be the most expensive kind of convenience.

It also says nothing about token decimals beyond those families, about how a particular contract rounds, or about the many places a chain’s own arithmetic has rules of its own. What it does show is the exact integer for any amount you give it, and whether the conversion was exact — which is the check worth having in front of you when you are about to sign something.

Every conversion above, including the 300000000000000040, is exact integer arithmetic done the way this article describes: parse the decimal string, scale by the unit’s own power of ten, and never let the value touch a float on the way.