IntersectMBO / IntersectMBO/evolution-sdk

Blockfrost: additionalUtxo evaluate serialization converts 64-bit amounts through Number(), rounding above 2^53

Open
#455 1 comment 0 reactions 0 assignees View on GitHub
bug external-review
Dominant language
TypeScript
Stars
22
Forks
30
Avg merge
5h 29m
Merged PRs (30d)
12

Description

## Summary
The Blockfrost provider's evaluateTx path serializes additional UTxOs by converting internal
bigint lovelace and asset quantities back through Number(), so any amount above 2^53 is rounded
before the request leaves the SDK. Note this is the OUTBOUND (evaluate) path only — Blockfrost's
inbound decode reads amounts as strings and is not affected. Fail closed: no fund loss; the
rounded additionalUtxo set produces incorrect local evaluation inputs and, for high-supply
tokens, an evaluate/tx result that does not match reality.

## Affected
packages/evolution/src/sdk/provider/internal/BlockfrostEffect.ts
- L89 toBlockfrostValue: coins: Number(assets.lovelace)
- L98 toBlockfrostValue: assetRecord[...] = Number(quantity)
reached via: toBlockfrostAdditionalUtxoSet (L148) -> evaluateTx (L706), POSTed to /utils/txs/evaluate/utxos (L729)
contrast (correct, inbound): Blockfrost.ts transformAmounts uses Schema.String -> BigInt.

## Fix
Emit lovelace and asset quantities as bigint-safe values in toBlockfrostValue (no Number(...)).
Blockfrost's evaluate endpoint expects the Ogmios-style JSON shape, so amounts must be emitted
as exact JSON integers via a lossless serializer, not as a quoted string (matching the same
constraint noted for the Ogmios send path in #406).

## Regression test
- given: an additional UTxO with lovelace 2^53+1 and a token quantity 2^64-1, run the evaluateTx
serialization and inspect the posted payload
- before fix: amounts are corrupted (2^53+1 -> 2^53, 2^64-1 -> 18446744073709552000)
- after fix: the serialized additionalUtxoSet contains the exact integers, round-tripping unchanged
Must FAIL on main today and PASS after the fix.

## Reference
Reported informally (large-value UTxO precision loss, Blockfrost outbound variant).
Related: #406 (Ogmios outbound, same bug class), #454 (Kupo inbound decode).

Contributor guide

Open the contributing guide

Research direction

Start in packages/evolution/src/sdk/provider/internal/BlockfrostEffect.ts at toBlockfrostValue (L89 and L98), then trace toBlockfrostAdditionalUtxoSet (L148) and evaluateTx (L706) to the POST at L729. Add the regression coverage described for lovelace 2^53+1 and token quantity 2^64-1, and verify the posted additionalUtxoSet preserves both exact integers.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.