Skip to content

FeeBumpFee int64 silently truncated to uint32 in TransformTransaction #400

@hunterpack

Description

@hunterpack

What version are you using?

docker pull stellar/stellar-etl:latest (bug introduced in commit eba446f, October 2023 — present in all versions since)

Check your version with:

docker run stellar/stellar-etl:latest stellar-etl version

Or via Go:

go list -m github.com/stellar/stellar-etl

What did you do?

Processed a ledger containing a fee-bump transaction where the outer fee (FeeBumpTransaction.Fee) exceeded 4,294,967,295 stroops (~429.5 XLM) using the export_transactions command:

stellar-etl export_transactions --start-ledger <ledger> --end-ledger <ledger> --output transactions.txt

Fee-bump transactions with high fees are realistic for resource-intensive Soroban smart contract executions or during network congestion. The Stellar XDR spec deliberately defines FeeBumpTransaction.Fee as Int64 to accommodate values above the Uint32 range.


What did you expect to see?

The new_max_fee field in the exported JSON (BigQuery) and Parquet output should reflect the correct int64 value of the fee-bump transaction's outer fee.

For example, a fee of 5,000,000,000 stroops should be exported as 5000000000.


What did you see instead?

new_max_fee is silently truncated to uint32, discarding the upper 32 bits.

Example: A fee of 5,000,000,000 stroops is exported as 705,032,704 (~70.5 XLM instead of ~500 XLM).

Root cause — three locations:

  1. internal/transform/transaction.go:294 — incorrect cast:

    // BUG: int64 cast to uint32, silently truncates upper 32 bits
    transformedTransaction.NewMaxFee = uint32(transaction.Envelope.FeeBumpFee())
    
    // FIX: should be
    transformedTransaction.NewMaxFee = transaction.Envelope.FeeBumpFee()
  2. internal/transform/schema.go:63 — wrong field type:

    // BUG
    NewMaxFee uint32 `json:"new_max_fee,omitempty"`
    
    // FIX
    NewMaxFee int64 `json:"new_max_fee,omitempty"`
  3. internal/transform/parquet_converter.go:82 — widens the already-corrupted value, so Parquet output also contains the wrong value. This will resolve automatically once the schema type is corrected.

Note: The same function correctly casts FeeBumpFee() to int64 at line 167 for InclusionFeeBid. The inconsistency is within the same function. All other fee fields in the schema (FeeCharged, ResourceFee, InclusionFeeBid, InclusionFeeCharged, ResourceFeeRefund) are correctly typed as int64.

Impact: Silent financial data corruption in both the BigQuery (JSON) and GCS (Parquet) export paths. Any downstream analytics, fee reconciliation, or compliance systems consuming this data will see incorrect new_max_fee values for affected transactions. Historical data since October 2023 may be affected.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions