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).
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
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
serialization and inspect the posted payload
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).