calculatorXCN Decimal Handling

Detailed guidance for handling native XCN amounts correctly across Solidity, JSON-RPC, wallets, and frontend code.

Critical Difference

triangle-exclamation

If you port code from Ethereum and keep 1 ether, 1e18, or "wei everywhere" assumptions for the native currency, you will introduce incorrect pricing, payment checks, and balance math.

At a Glance

Context
Unit / Scale
Decimals
Examples

Solidity / EVM execution

tinyxcn

8

msg.value, address(this).balance, transfer, send, call{value: ...}

JSON-RPC and wallets

18-decimal native amount

18

eth_getBalance, provider.getBalance, transaction value, gasPrice, maxFeePerGas

ERC-20 token balances

Token-defined

Usually 18, but not guaranteed

balanceOf, transfer, decimals()

The 8-vs-18 rule applies to the native currency only. Do not apply the 10^10 conversion factor to ERC-20 tokens.

Conversion Rule

For native XCN:

1 XCN      = 100,000,000 tinyxcn = 10^8 tinyxcn
1 XCN      = 1,000,000,000,000,000,000 RPC units = 10^18
1 tinyxcn  = 10,000,000,000 RPC units = 10^10

That gives you the two conversions you need:

What This Means in Practice

Inside contracts: always think in tinyxcn

When Solidity code handles native value, the amount is always in tinyxcn:

  • msg.value

  • address(this).balance

  • payable(addr).transfer(amount)

  • payable(addr).send(amount)

  • payable(addr).call{value: amount}("")

1 XCN inside a contract is:

Not:

Outside contracts: JSON-RPC uses 18-decimal scaling

Wallets, libraries, and RPC endpoints expose native balances and transaction value in the familiar 18-decimal Ethereum format:

That value arrives inside the contract as:

Your own function parameters are application-defined

If you write a function like deposit(uint256 amount) or quote(uint256 amount), the chain does not reinterpret that integer for you. You must choose the unit and document it.

For native-value APIs, the safest convention is:

  • Accept native amounts in tinyxcn

  • Name them clearly, for example amountTinyxcn

  • Emit events with unit names in the field names

Solidity Patterns

Use explicit constants

Do not use:

  • 1 ether

  • 0.1 ether

  • 1e18

  • any hardcoded "wei-style" native constants copied from Ethereum contracts

Payable checks

Event naming should include units

Avoid ambiguous fields like amount if the surrounding code also deals with 18-decimal RPC values off-chain.

Receiving XCN in Contracts

Solidity receive and fallback behavior works as EVM developers expect when the value transfer goes through the EVM path.

If native XCN is sent to a contract through an EVM contract call:

  • receive() runs when calldata is empty

  • fallback() runs when calldata does not match a function selector and the fallback is payable

Example:

circle-exclamation

This distinction matters for:

  • deposit contracts that credit balances on receipt

  • escrow contracts that must validate senders

  • accounting contracts that emit events when funds arrive

  • upgradeable systems that depend on payable entrypoints

If the business logic must run, expose an explicit payable function such as deposit() and route users there.

Sending XCN From Contracts

The usual Solidity mechanisms are supported:

  • transfer()

  • send()

  • call{value: ...}("")

Example:

For modern Solidity code, call is generally the most flexible choice. Whatever transfer mechanism you use, the amountTinyxcn parameter is still an 8-decimal native amount.

Frontend and RPC Guidance

Sending 1.5 XCN from a dApp

The transaction is submitted through RPC using 18-decimal scaling, but the contract receives:

Reading balances

  • rpcBalance is the 18-decimal RPC value

  • xcn is the human-readable XCN string

  • tinyxcn matches what Solidity would see from address(contractAddress).balance

Use BigInt, not JavaScript Number, for raw amounts.

Example: Same Balance, Two Representations

Assume an account holds 9,000,099.81460509 XCN.

Inside Solidity:

Via JSON-RPC:

The ratio is exactly 10^10.

ERC-20 and Other Token Amounts

Do not generalize native XCN rules to token contracts.

  • ERC-20 amounts use the token's own decimals() setting

  • Many ERC-20 tokens use 18 decimals, but not all do

  • NFT standards do not use this native-value conversion model

  • The 10^10 factor is only for converting native XCN between Solidity/EVM and JSON-RPC representations

Testing Guidance

A good test should assert both views of the same transfer:

Also search migrated contracts for:

  • ether

  • 1e18

  • parseEther values compared directly against contract-side amounts

  • event names that hide units

  • comments claiming msg.value is 18 decimals

Migration Checklist

  • Replace native ether constants with tinyxcn constants

  • Audit every msg.value check

  • Audit every address.balance comparison

  • Standardize off-chain conversion helpers

  • Name native-amount variables with Tinyxcn suffixes when possible

  • Ensure payable flows go through an EVM contract call if contract logic must execute

  • Add tests that compare RPC values and contract-side values for the same transfer

Summary

circle-check

Last updated