Skip to content

fix(monitoringV2): cast NUMERIC columns to text in challenge raw query#32

Merged
TaprootFreak merged 1 commit into
developfrom
fix/challenge-bigint-precision
May 10, 2026
Merged

fix(monitoringV2): cast NUMERIC columns to text in challenge raw query#32
TaprootFreak merged 1 commit into
developfrom
fix/challenge-bigint-precision

Conversation

@TaprootFreak

Copy link
Copy Markdown
Contributor

Problem

JDM (mainnet) monitoring container has been in a sustained crash with 14+ consecutive failures:

```
ERROR [MonitoringService] Error occurred while processing blocks (14 consecutive failures):
SyntaxError: Cannot convert 2.83917438483003551495e+22 to a BigInt
at ChallengeRepository.findActiveWithChallengePeriod (challenge.repository.js:85:31)
```

This is a release-blocker for #30 Release: develop → main — if it merges as-is, dfxprd will pick up the same crash the moment a single challenge with size > 2^53 wei (~9 JUSD) lands on the mainnet hub.

Root cause

`findActiveWithChallengePeriod` uses `$queryRaw` to select `size` and `current_price` from `challenge_states`. Both columns are `NUMERIC(78,0)`. Without an explicit cast, Prisma's raw query path returned them as JS `number`, which:

  1. silently loses precision past `Number.MAX_SAFE_INTEGER` (2^53 - 1)
  2. serialises via `.toString()` in scientific notation for very large values

`BigInt()` rejects scientific notation → throw. JDT was unaffected because testnet challenges never crossed 2^53 wei.

Fix

Mirror the pattern already in `position.repository.ts`: explicit `::text` casts in the SQL, typed as `string` in the row shape, then `BigInt(r.size)` directly without an intermediate `.toString()`.

```diff

  •   const rows = await this.prisma.\$queryRaw<
    
  •   const rows = await this.prisma.\$queryRaw<
      	Array<{
      		...
    
  •   		size: any;
    
  •   		current_price: any;
    
  •   		size: string;
    
  •   		current_price: string;
      		...
      	}>
      >\`
      	SELECT c.challenge_id, c.hub_address, c.challenger_address, c.position_address,
    
  •   	       c.start_timestamp, c.size, c.current_price, c.t24_alerted, c.t2_alerted,
    
  •   	       c.start_timestamp,
    
  •   	       c.size::text         as size,
    
  •   	       c.current_price::text as current_price,
    
  •   	       c.t24_alerted, c.t2_alerted,
      	       p.challenge_period
    

```

Scope

Test plan

  • After deploy to dfxdev, verify JDM monitoring container processes a full cycle without the `Cannot convert` exception (currently 14 consecutive failures).
  • Verify JDT continues to work (no regression).
  • Verify deadline watchdog (T-24h / T-2h) still fires correctly — values now arrive as `bigint` instead of via toString-bigint round trip.

`findActiveWithChallengePeriod` selects `size` and `current_price` from
`challenge_states`, both NUMERIC(78,0). Prisma's `$queryRaw` was
materialising the values as JS `number`, which loses precision for
values beyond 2^53 and serialises them via `.toString()` in scientific
notation (e.g. `2.8391...e+22`). `BigInt()` does not accept that
format, so the monitoring cycle crashed with
"Cannot convert <sci-notation> to a BigInt" on mainnet — JDM has
challenges over 28391.7 JUSD (28.4e21 wei), JDT does not, which is why
only JDM was affected.

Fix mirrors the pattern already used in `position.repository.ts`:
explicit `::text` casts in the SQL, typed as `string` in the row
shape, then `BigInt(r.size)` directly without an intermediate
`.toString()`.
@TaprootFreak TaprootFreak marked this pull request as ready for review May 10, 2026 22:24
@TaprootFreak TaprootFreak merged commit a238817 into develop May 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant