fix(rpc): felt types serialize as u64 limbs instead of hex strings#3504
Merged
rodrodros merged 1 commit intoNethermindEth:mainfrom Mar 24, 2026
Merged
Conversation
5 tasks
39bff64 to
90031aa
Compare
rodrodros
approved these changes
Mar 24, 2026
90031aa to
5d3d697
Compare
Contributor
|
I forced push just to rebase from main (sorry if you'd already done it) |
brbrr
pushed a commit
that referenced
this pull request
Mar 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
being serialized as
[u64, u64, u64, u64]Montgomery limbs instead of"0x..."hex stringsMarshalJSONfrom pointer to value receiver on all felt types (Felt,Hash,TransactionHash,Address,ClassHash,SierraClassHash,CasmClassHash,StateRootHash)anyinterface (reproducing the jsonrpcserver's serialization path)
Rationale
Go's
encoding/jsoncannot call pointer-receiver methods on non-addressable values. The jsonrpcserver stores handler return values in
response.Result any(server.go:519):Values extracted from
anyvia reflection are not addressable. Since all feltMarshalJSONmethods used pointer receivers (
*Felt,*Hash, etc.),encoding/jsoncould not call themand fell back to encoding the underlying
[4]uint64as a JSON array.This violates the Starknet RPC spec
which defines
FELTas"type": "string", "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,62})$".Observed behavior
{ "transaction_hash": [10235509696732094000, 15042186987767562000, 2604752151520920600, 522667376275625800] }Expected behavior
{ "transaction_hash": "0x8de..." }Timeline
feat(core): add new types for core felt based types (#3125)TransactionHash,Address,Hash, etc. as named types — withoutMarshalJSONfix: json marshalling (#3244)MarshalJSONto the new types, but with pointer receivers — the root causefeat(rpcv10): response_flags; proof_facts, proof (#3380)AddTxResponse.TransactionHashchanged from*felt.Felt→felt.TransactionHash(value) — bug becomes observableThe underlying issue (
Felt.MarshalJSONusing a pointer receiver) existed since thecore/feltpackage was created, but was latent because all response structs used
*felt.Felt(pointer fields).It only surfaced when v10 introduced value-type felt fields in handler return structs.
Changelog
Fixed
starknet_addInvokeTransactionreturningtransaction_hashas an array of u64 limbs insteadof a hex string, breaking starknet.js and other clients that expect the spec-compliant format
Felt,Hash,Address,TransactionHash,ClassHash,SierraClassHash,CasmClassHash,StateRootHash) now serialize correctly as hex stringseven when used as value fields in structs passed through
anyinterfacesTest plan
TestMarshalJSON_ValueInInterfacereproduces the bug across all felt typesgo test ./core/felt/...— all passgo test ./rpc/...— all pass (v6 test updated to expect correct hex output)go test ./jsonrpc/...— all passgo test ./adapters/...— all pass