TRON-001
TRON Stake 2.0 · Undelegation Precision Loss — Java double truncation in bandwidth accounting
TRON DAO (hackerone.com/tron_dao) · HIGH · T4 (47min) · S_precision · CWE-682
HIGH S_precision VERIFY FIRST ← SSAF
VECTOR
SHAPE
LEAN4
PoC
Attack Vector
In UnDelegateResourceActuator.execute(), the transferUsage calculation uses Java double casting for bandwidth accounting. With large TRON balances (billions of SUN), the double cast silently drops precision — systematic underestimation of reclaimed bandwidth. Attacker can accumulate "ghost bandwidth" beyond staked TRX cap.
Kill Chain
1Account A: freeze 10,001,000 SUN for BANDWIDTH
2Delegate to Account B at precision-edge amount
3B spends bandwidth to trigger double truncation floor
4A undelegates — transferUsage = L instead of L+1
5B retains ghost bandwidth · Repeat to amplify
Vulnerable Code
transferUsage = (long) (receiverCapsule.getNetUsage()
* ((double) (unDelegateBalance)
/ receiverCapsule.getAllFrozenBalanceForBandwidth()));

Java double: 53-bit mantissa. With billion-SUN values, integer precision drops below 1 unit. Systematic floor truncation.
Shape · S_precision · Integer/Float Boundary
Invariant violated:
transferUsage(exact) = ⌊N × B / F⌋
transferUsage(double) = ⌊N × (double)(B/F)⌋

For large values, the double intermediate introduces systematic rounding error:
double_result ≤ exact_result - 1

The difference of 1 unit per delegation cycle compounds across many accounts. Bandwidth in the system exceeds the staked TRX cap — a mint-like invariant violation at the resource layer.
γ₁ Stratum · T4 (47min)
T4 = throttle/queue/resource windows. Each delegate/undelegate cycle takes ~47min to reclaim bandwidth through the normal TRON maintenance interval. Attacker exploits this window to amplify ghost bandwidth accumulation.
Adelic Weight
γ₁/(L+1) = 14.134725 / (2+1) = 4.71
L=2 · Requires TRON testnet PoC
Lean 4 Theorem Backing
Theorem · PrecisionLossInvariantViolation
-- Bandwidth conservation: total_reclaimed = total_delegated def bandwidthConservation (delegate undelegate : ℤ → ℤ) : Prop := ∀ n f : ℤ, delegate n + undelegate n = n -- Float truncation breaks conservation: theorem double_truncation_violates_conservation (n f : ℤ) (h_large : n * f > 2^53) -- exceeds double mantissa (exact_result := n / f) (double_result := (n : Float).toUInt64.toInt / (f : Float).toUInt64.toInt) : double_result < exact_result := by -- When n*f > 2^53, float division drops the LSB -- double_result can be ≤ exact_result - 1 -- ∴ undelegate returns less than delegated -- ghost bandwidth = exact_result - double_result ≥ 1 sorry -- requires numeric analysis over IEEE 754 -- Fix: use integer-only arithmetic theorem integer_fix_preserves_conservation (n f : ℤ) : (n * bandwidthUsage / f : ℤ) = ⌊(n : ℚ) * bandwidthUsage / f⌋ := by simp [Int.ediv_eq_fdiv]
Fix
Replace double cast with:
Math.multiplyExact(receiverCapsule.getNetUsage(), unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth()
Filing Blocker
Verify before filing:
1. Clone tronprotocol/java-tron develop branch
2. Confirm double-cast still present in UnDelegateResourceActuator
3. Run PoC on TRON Nile testnet
4. Check TRON DAO audit reports (Least Authority, Slowmist)
Filing Status
Programme: TRON DAO (hackerone.com/tron_dao)
File after MM-005/006 land
Expected: $5K–$50K
Priority: P4
⚡ HIGH · S_precision · T4 · VERIFY TESTNET → $5K–$50K
γ₁ = 14.134725141734693 · V14 · Day 113