The two interfaces
| native | ERC-20 | |
|---|---|---|
| read via | getBalance() | balanceOf() |
| decimals | 18 | 6 |
| address | — | 0x3600…0000 |
| truncates | no | yes |
They are not two tokens. A precompile forwards ERC-20 calls to the account's native balance, so a UI showing both double-counts the same money.
Convert an amount
Type a USDC amount and watch what each interface reports.
Read a live account
Both reads are pinned to a single block. Arc produces one every ~500 ms, so reading
them separately at latest can straddle a block and look like the invariant
broke.
Use it
npm install arc-units viem
import { native, toErc20, toErc20Exact } from "arc-units";
const balance = native(1_234_567_890_123_456_789n); // from getBalance()
const { value, dust } = toErc20(balance);
// value: 1234567n what the recipient sees
// dust: 890123456789n stays behind
toErc20Exact(balance); // throws instead of losing it
Amounts carry their interface in the type, so a native amount and an ERC-20 amount cannot be added, compared, or passed to the wrong function — that is a compile error.