Skip to content

[UTXO-BUG] CRIT-2: Dual-write decimal mismatch inflates account model 10x#2068

Closed
ArokyaMatthew wants to merge 1 commit intoScottcjn:mainfrom
ArokyaMatthew:utxo-bug/crit2-dualwrite-decimal-mismatch
Closed

[UTXO-BUG] CRIT-2: Dual-write decimal mismatch inflates account model 10x#2068
ArokyaMatthew wants to merge 1 commit intoScottcjn:mainfrom
ArokyaMatthew:utxo-bug/crit2-dualwrite-decimal-mismatch

Conversation

@ArokyaMatthew
Copy link
Copy Markdown
Contributor

Vulnerability Class

Critical — Fund inflation via precision error (200 RTC bounty)

The Bug

The UTXO model uses UNIT = 100_000_000 (10^8, 8 decimal places). But the dual-write path in utxo_endpoints.py line 320 converts to the account model using 1_000_000_000 (10^9, 9 decimal places):

# UTXO model (correct):
amount_nrtc = int(amount_rtc * UNIT)          # 10 RTC → 1,000,000,000

# Dual-write to account model (WRONG):
amount_i64 = int(amount_rtc * 1_000_000_000)  # 10 RTC → 10,000,000,000 (10x!)

Every transfer with dual_write=True credits 10× the correct amount in the account-model balance table.

Impact
Account model shows 10× more funds than actually exist in UTXOs
Integrity checks (/utxo/integrity) will always fail once dual-write is enabled
When UTXO becomes authoritative, the mismatch causes phantom balances or masks real bugs
Fix
Use amount_nrtc (already correctly computed from amount_rtc * UNIT) instead of re-converting from the float with the wrong multiplier.

Test Added
TestDualWriteConsistency.test_dual_write_amount_matches_utxoenables dual-write, transfers 60 RTC, verifies account model gets exactly 60 * UNIT (not 60 * 10^9)
All 16 endpoint tests pass.

Files Changed
node/utxo_endpoints.py1 line changed (fixed multiplier)
node/test_utxo_endpoints.py88 lines added (new test class)
Ref: Bounty #2819

MY WALLET IS aroky-x86-miner 

… 10x

The UTXO model uses UNIT = 10^8 (8 decimal places), but the dual-write
path in utxo_endpoints.py line 320 converts with 10^9 (9 decimals):

  amount_i64 = int(amount_rtc * 1_000_000_000)  # WRONG: 10x too large

Every transfer with dual_write=True credits 10x the correct amount in
the account model. When the UTXO system becomes authoritative, the
integrity check will always fail, and the account model will show
phantom balances.

Fix: use amount_nrtc (already correctly computed via UNIT) instead of
re-converting from the float amount_rtc.

Test added:
- TestDualWriteConsistency.test_dual_write_amount_matches_utxo

All 16 endpoint tests pass.

Bounty: #2819 (Critical, 200 RTC)
@github-actions github-actions bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) node Node server related labels Apr 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Your PR has a BCOS-L1 or BCOS-L2 label
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@zhuzhushiwojia
Copy link
Copy Markdown

Great security audit work! These fixes are critical for the protocol.

@Scottcjn
Copy link
Copy Markdown
Owner

Scottcjn commented Apr 5, 2026

Closing as duplicate of createkr #2096 (already merged), which fixed the same dual-write unit mismatch (1e9 → correct UNIT).

25 RTC independent discovery credit — you found the same bug independently, which validates the severity. Good eye.

Wallet: ArokyaMatthew | Reason: independent discovery bounty #2819 CRIT-2 (dupe of #2096)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) node Node server related size/M PR: 51-200 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants