refactor(stdlib): a function's return type is a single optional AbiType - #25066
Open
nchamo wants to merge 3 commits into
Open
refactor(stdlib): a function's return type is a single optional AbiType#25066nchamo wants to merge 3 commits into
nchamo wants to merge 3 commits into
Conversation
nchamo
marked this pull request as ready for review
July 30, 2026 18:33
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.
Why we are doing this
FunctionAbi.returnTypesis anAbiType[], but it can only ever hold zero or one entry: Noir emitsreturn_type: AbiType | null, and a function returning several values expresses them as a singletupletype. The listshape invites callers to handle a case that cannot occur, and every consumer that wants the return type has to reach
for index 0 and decide what an empty list means.
Our fix
FunctionAbigains a single optionalreturnType, andreturnTypesstays as a deprecated field written alongside it,so artifacts and RPC payloads serialized before this change still resolve. Both are read through
getFunctionReturnType, which prefers the singular field and falls back to the deprecated list. Reading a list withmore than one entry throws rather than silently dropping the extra entries, since the value feeds contract class ids.
computeFunctionMetadataHashkeeps hashing the type as a one-element list. That preimage is what contract class ids andtherefore deployed addresses are derived from, so its shape is frozen regardless of how the field is stored; the
standard-contract address pins confirm nothing moved.
FunctionCallgets the same treatment on the wire:returnTypeis the field,returnTypesis accepted on parse andemitted on serialization for peers that still require it.
Decoding is split by role, which the old single entry point conflated:
decodeFromAbitakes the one type a function returns (orundefined) and returns one decoded value. A function thatreturns nothing now decodes to
undefinedwhere it previously produced[].decodeEachFromAbitakes a list of types and returns one decoded value per type, which is how a function's argumentsare encoded. It always returns a list, fixing a latent bug where a single-argument function decoded to a bare value
and callers indexing
[0]gotundefined.Fixes #25040