We want the asi coin/token on asi chain match the 18 decimals of the token on ethereum, but currently our node is set to use only 64 bit, where 256 bit is the standard on ethereum.
I used claude to investigate and produce the text below trying to be as exact as possible with paths to the relevant files.
Why Int is hard-capped at 2^63−1
Rholang Int is sint64 by grammar + normalizer, not convention:
rholang/src/main/bnfc/rholang_mercury.cf:5 — position token LongLiteral digit+; (literal token literally named Long).
rholang/src/main/bnfc/rholang_mercury.cf:168,196 — GroundInt ::= LongLiteral; SimpleType ::= "Int" (reserved keyword).
rholang/.../normalizer/GroundNormalizeMatcher.scala:24 — gi.longliteral_.toLong → JVM Long.parseLong. Any literal > 9_223_372_036_854_775_807 throws NumberFormatException → NormalizerError at compile time.
models/.../protobuf/RhoTypes.proto:196 — sint64 g_int = 2; (wire format).
- Separate ground type exists:
g_big_int = 35 (BigInt, arbitrary precision, literal suffix I). Different type — match Int will not match a BigInt.
Problem
System vault pinned to Int:
casper/src/main/resources/NonNegativeNumber.rho:53 — match init { Int => ... } rejects BigInt.
casper/src/main/resources/NonNegativeNumber.rho:22 — overflow guard v + x >= v assume i64 wrap; meaningless on BigInt.
casper/src/main/resources/MakeMint.rho:25,58,134,154 — forwards init/amount through the same i64 channel; every purse inherits the ceiling.
Hard cap: 9_223_372_036_854_775_807 base units. At 18 decimals → ~9.22 tokens. Bridge work around it with SCALE = 10^10 (ASI 8-dec vs ETH 18-dec, snet/asi-bridge/decimal-scaling.md) — costs precision on dust, needs amount % SCALE == 0 guard on EVM side.
Ask
Accept BigInt in vault so 18-dec / uint256-shaped amounts work without scaling.
Min changes:
NonNegativeNumber.rho:53 — match BigInt (replace or widen Int arm).
NonNegativeNumber.rho:22 — replace i64-wrap check with x >= 0I && v + x >= 0I (BigInt has no wrap, only need non-negativity).
- Re-register under new URI — existing
rho:id:hxyadh1ffypra47ry9mk6b8r1i33ar1w9wjsez4khfe9huzrfcytx9 sealed (nonce = Long.MaxValue at NonNegativeNumber.rho:64, registry strict > at Registry.rho:602 → no successor possible).
MakeMint.rho — no logic change; point lookup at new URI. Re-register under new URI too.
Acceptance
MakeMint!("makePurse", 10^30I, *p) returns purse; getBalance = 10^30I.
add / sub round-trip past 2^63−1 without truncation.
bridge.rho re-pointed at widened vault, accepts wei directly, SCALE = 10^10 removed.
Open
- Rho interpreter
BigInt ops on hot path — does + - >= <= and equality vs 0I work end-to-end? Real blocker if not.
- Merge/replay on
@(*MergeableTag, *valueStore) under multi-parent — identical for BigInt-tagged channels? Deliberate test needed; already lost writes on Long-backed bridge channel under multi-parent fork.
- Phlo cost — BigInt add vs Int add on transfer hot path; budgets need re-tune?
Refs
casper/src/main/resources/NonNegativeNumber.rho
casper/src/main/resources/MakeMint.rho
casper/src/main/resources/SystemVault.rho
casper/src/main/resources/Registry.rho
rholang/src/main/bnfc/rholang_mercury.cf
rholang/src/main/scala/coop/rchain/rholang/interpreter/compiler/normalizer/GroundNormalizeMatcher.scala
models/src/main/protobuf/RhoTypes.proto
We want the asi coin/token on asi chain match the 18 decimals of the token on ethereum, but currently our node is set to use only 64 bit, where 256 bit is the standard on ethereum.
I used claude to investigate and produce the text below trying to be as exact as possible with paths to the relevant files.
Why
Intis hard-capped at 2^63−1Rholang
Intis sint64 by grammar + normalizer, not convention:rholang/src/main/bnfc/rholang_mercury.cf:5—position token LongLiteral digit+;(literal token literally named Long).rholang/src/main/bnfc/rholang_mercury.cf:168,196—GroundInt ::= LongLiteral;SimpleType ::= "Int"(reserved keyword).rholang/.../normalizer/GroundNormalizeMatcher.scala:24—gi.longliteral_.toLong→ JVMLong.parseLong. Any literal >9_223_372_036_854_775_807throwsNumberFormatException→NormalizerErrorat compile time.models/.../protobuf/RhoTypes.proto:196—sint64 g_int = 2;(wire format).g_big_int = 35(BigInt, arbitrary precision, literal suffixI). Different type —match Intwill not match aBigInt.Problem
System vault pinned to
Int:casper/src/main/resources/NonNegativeNumber.rho:53—match init { Int => ... }rejectsBigInt.casper/src/main/resources/NonNegativeNumber.rho:22— overflow guardv + x >= vassume i64 wrap; meaningless onBigInt.casper/src/main/resources/MakeMint.rho:25,58,134,154— forwardsinit/amountthrough the same i64 channel; every purse inherits the ceiling.Hard cap:
9_223_372_036_854_775_807base units. At 18 decimals → ~9.22 tokens. Bridge work around it withSCALE = 10^10(ASI 8-dec vs ETH 18-dec,snet/asi-bridge/decimal-scaling.md) — costs precision on dust, needsamount % SCALE == 0guard on EVM side.Ask
Accept
BigIntin vault so 18-dec / uint256-shaped amounts work without scaling.Min changes:
NonNegativeNumber.rho:53— matchBigInt(replace or widenIntarm).NonNegativeNumber.rho:22— replace i64-wrap check withx >= 0I && v + x >= 0I(BigInt has no wrap, only need non-negativity).rho:id:hxyadh1ffypra47ry9mk6b8r1i33ar1w9wjsez4khfe9huzrfcytx9sealed (nonce =Long.MaxValueatNonNegativeNumber.rho:64, registry strict>atRegistry.rho:602→ no successor possible).MakeMint.rho— no logic change; point lookup at new URI. Re-register under new URI too.Acceptance
MakeMint!("makePurse", 10^30I, *p)returns purse;getBalance=10^30I.add/subround-trip past2^63−1without truncation.bridge.rhore-pointed at widened vault, accepts wei directly,SCALE = 10^10removed.Open
BigIntops on hot path — does+ - >= <=and equality vs0Iwork end-to-end? Real blocker if not.@(*MergeableTag, *valueStore)under multi-parent — identical for BigInt-tagged channels? Deliberate test needed; already lost writes on Long-backed bridge channel under multi-parent fork.Refs
casper/src/main/resources/NonNegativeNumber.rhocasper/src/main/resources/MakeMint.rhocasper/src/main/resources/SystemVault.rhocasper/src/main/resources/Registry.rhorholang/src/main/bnfc/rholang_mercury.cfrholang/src/main/scala/coop/rchain/rholang/interpreter/compiler/normalizer/GroundNormalizeMatcher.scalamodels/src/main/protobuf/RhoTypes.proto