Skip to content

Integer Scaling Protection Failure in Resource Deposit/Burnback Reconciliation #5

Description

@elizabetheonoja-art

Integer Scaling Protection Failure in Resource Deposit/Burnback Reconciliation

Problem Statement

The contracts/src/resource_tokenization/reconciliation.rs module reconciles on-chain token supply with off-chain resource deposit attestations. The reconcile_deposit() function at line 110 computes tokens_to_mint = deposit_amount * TOKEN_SCALE_FACTOR / ASSET_PRECISION, where TOKEN_SCALE_FACTOR = 10^18 and ASSET_PRECISION = 10^6 (micro-units for commodity measurement). When deposit_amount is very large (e.g., 9.22e18 micro-units of water), the intermediate multiplication deposit_amount * TOKEN_SCALE_FACTOR = 9.22e36 overflows u128::MAX (3.4e38 is the limit, but 9.22e36 is close). However, a crafted input of deposit_amount = 340282366920938463463374607431768211455 (u128::MAX) paired with ASSET_PRECISION = 1 causes u128::MAX * 10^18 to overflow silently, wrapping to a small value. This allows minting tokens worth only 0.0001% of the deposited resource, or conversely — if ASSET_PRECISION is configured incorrectly — minting vastly more tokens than the deposited resource value.

State Invariants & Parameters

  • TOKEN_SCALE_FACTOR: 10^18 (18 decimals — Soroban token standard)
  • ASSET_PRECISION: configurable, range [1, 10^12]
  • MAX_DEPOSIT_AMOUNT: u128::MAX / TOKEN_SCALE_FACTOR (safe bound)
  • Reconciliation grace period: 100 ledger closes (~500s)
  • Invariant: tokens_minted * ASSET_PRECISION ≈ deposit_amount * TOKEN_SCALE_FACTOR within precision tolerance

Affected Code Paths

  • contracts/src/resource_tokenization/reconciliation.rs:105-140reconcile_deposit() multiplication without overflow check
  • contracts/src/resource_tokenization/config.rs:30-55ASSET_PRECISION configuration with no bounds validation
  • contracts/src/resource_tokenization/tests/reconciliation_tests.rs — No overflow edge-case tests

Resolution Blueprint

  1. Add a pre-validation guard in reconcile_deposit(): require!(deposit_amount <= MAX_SAFE_DEPOSIT, "deposit exceeds safe computation range") where MAX_SAFE_DEPOSIT = u128::MAX / TOKEN_SCALE_FACTOR.
  2. Replace checked_mul().checked_div() pattern: compute tokens_to_mint = deposit_amount.checked_mul(TOKEN_SCALE_FACTOR).ok_or(OverflowError)?.checked_div(ASSET_PRECISION).ok_or(DivByZeroError)?. Return Err instead of panicking to allow graceful rejection.
  3. Add config bounds: require!(ASSET_PRECISION >= 1 && ASSET_PRECISION <= 10^12, "invalid precision") at configuration time.
  4. Implement a SafeScale utility struct in contracts/src/resource_tokenization/safe_scale.rs that tracks intermediate results as (numerator: U256, denominator: U256) using the uint crate for 512-bit arithmetic, then converts back to u128 at the end.
  5. Add property-based tests with randomly generated deposit_amount ∈ [0, u128::MAX] and ASSET_PRECISION ∈ [1, 10^12], verifying |result_u128 - exact_u256| <= 1 (rounding error at most 1 base unit).

Labels

  • Complexity: Hardcore
  • Layer: Core-Engine
  • Type: Race-Condition

Metadata

Metadata

Assignees

Labels

Complexity: HardcoreIssues requiring deep systems-level engineering rigorGrantFox OSSIssue tracked in GrantFox OSSLayer: Core-EngineCore contract engine layerMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignType: Race-ConditionConcurrency and race condition related issues

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions