Skip to content

Misordered named parameters bug blog post - #205

Draft
nikola-matic wants to merge 1 commit into
mainfrom
misordered-named-parameters-in-require-with-custom-errors-bug
Draft

Misordered named parameters bug blog post#205
nikola-matic wants to merge 1 commit into
mainfrom
misordered-named-parameters-in-require-with-custom-errors-bug

Conversation

@nikola-matic

Copy link
Copy Markdown
Collaborator

Date TBD

layout: post
published: true
title: 'Misordered Named Parameters in require with Custom Errors Bug'
date: '2026-05-20'

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget

category: Security Alerts
---

On February 9, 2026, the Solidity team discovered a bug in the IR-based code generator that

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know the actual reporter (aside from the EF bug bounty), and should we use them instead of "Solidity team"?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was people from Spearbit. Hari will know.

Or you can ping EF - we still did not notify them that we changed the severity of this after our initial response and did not send impact analysis.

@nikola-matic
nikola-matic requested review from cameel and czepluch May 19, 2026 10:47
@nikola-matic nikola-matic self-assigned this May 19, 2026

@czepluch czepluch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. mostly cosmetic nits from my side.

@nikola-matic
nikola-matic force-pushed the misordered-named-parameters-in-require-with-custom-errors-bug branch from 6275181 to a708add Compare July 21, 2026 13:31
@netlify

netlify Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploy Preview for solidity-website ready!

Name Link
🔨 Latest commit 2a1511e
🔍 Latest deploy log https://app.netlify.com/projects/solidity-website/deploys/6a74fbe41df5bc0008f13173
😎 Deploy Preview https://deploy-preview-205--solidity-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@cameel cameel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wording and minor inaccuracies. The overall structure is fine.


The bug was introduced in Solidity 0.8.26, which added support for passing custom errors as
the second argument to `require`.
[Solidity 0.8.37](https://github.com/ethereum/solidity/releases/tag/v0.8.37), released on May 20, 2026, provides a fix.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This date needs to be updated too, but I'd actually just omit it. Specifying version is unambiguous enough.


We assigned the bug a severity of "very low".
The affected code is the construction of revert data for a transaction that is already going
to revert, so contract state is not modified by it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
to revert, so contract state is not modified by it.
to revert, so it has no impact on contract's state.


## Technical Details

A custom error declaration fixes the order of its parameters, and that order determines its

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A custom error declaration fixes the order of its parameters, and that order determines its
A custom error declaration specifies the order of its parameters, and that order determines its

Comment on lines +59 to +60
Solidity also allows the caller to pass arguments by name, optionally in a different order
from the declaration:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"also" here sounds weird, as if you just showed the version with positional arguments, but you did not.

Suggested change
Solidity also allows the caller to pass arguments by name, optionally in a different order
from the declaration:
Solidity allows the caller to pass arguments by name, optionally in a different order
from the declaration:

Comment on lines +69 to +70
by any reordering. Most surprisingly, this includes reorderings of two arguments of the same
type, where no positional type mismatch could ever surface.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that surprising? To me it's actually the more obvious case. Lack of type mismatch means that the compiler or decoder can't detect it so no compilation or runtime error can save you. It's the fact that the compiler won't fail trying to encode mismatched types that was more surprising to me.

Comment on lines +89 to +91
reordered with respect to a value-type argument, the slots passed to the encoding helper are
permuted at the level of *stack slots*, not at the level of named parameters, and the helper
interprets its inputs against parameter positions of a different width than intended.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are not permuted as individual stack slots. They're still grouped. Just in the wrong way.

Also, "parameter positions of a different width" sounds weird to me. I know what you mean, but only because I already know how the bug works. Generally, referring to it as "width" or "stack width" sounds wrong.

Comment on lines +109 to +110
field is therefore read from a value-type slot, and the string data is copied from an
arbitrary calldata offset.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
field is therefore read from a value-type slot, and the string data is copied from an
arbitrary calldata offset.
field is therefore read from a value-type slot, and the string data is copied from a
random calldata offset.

Comment on lines +112 to +114
In the most severe configurations the encoding aborts with an EVM-level error, which still
causes the transaction to revert - but with no decodable error data - rather than producing
the intended custom-error revert. In less severe configurations the payload is well-formed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say that the latter is worse, because it's sometimes possible for the receiver to successfully decode it.

Actually, the current text makes it sound like the data can never be decoded. Often it actually can. It's just numbers. A small integer can easily pass for a valid offset.

reorders arguments before encoding, and so are not affected. The bug is specific to the
`require`-with-custom-error path introduced in 0.8.26.

### Misalignment With Mixed Stack Widths

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mention two cases in the post:

  • swapping parameters of the same type
  • swapping parameters of different types represented using different numbers of stack slots

The third possibility is missing: different types with same numbers of stack slots. It's also not considered in the impact section.

Comment on lines +119 to +132
## Impact

Because the bug affects only the construction of revert data for transactions that are
already going to revert, it cannot be used to manipulate storage, return values, or external
calls. Its primary consequence is misleading off-chain consumers - block explorers, indexers,
error-decoding libraries, and test frameworks - that decode the payload as if the values had
been placed correctly. In the stack-misalignment cases the failure is more visible: an
encoding-level revert can replace the intended custom-error revert, so off-chain code that
distinguishes specific custom errors from generic reverts may take a different branch than
expected.

Named-argument syntax is uncommon in `require` calls in practice, and the bug remained
undetected for almost two years. The narrow trigger conditions and the read-only nature of the
affected code path together place this bug in the "very low" severity tier.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • It can have on-chain effects - reverts can be intercepted with try/catch or by using a bare call. It's just that this is not (and should not be) commonly done.
  • Do we want to also mention the ERC that made us reconsider the severity of this?

@nikola-matic
nikola-matic force-pushed the misordered-named-parameters-in-require-with-custom-errors-bug branch 2 times, most recently from 66d46e8 to 04ca6ff Compare August 6, 2026 13:37
@nikola-matic
nikola-matic force-pushed the misordered-named-parameters-in-require-with-custom-errors-bug branch from 04ca6ff to 2a1511e Compare August 6, 2026 21:25

@clonker clonker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small comments. Should we mention that the revert always happens? (it does, doesn't it? just with weird data).


## Which Contracts Are Affected?

A contract is affected when **all** of the following conditions hold:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string/bytes literals are inserted directly at declaration order, so these are unaffected as far as i can tell - then you'd need at least two non-string/byte lit named args

The encoding helper for `StringAndUint` expects to first receive the two slots that describe
`a` (the calldata string's offset and length), followed by the single slot that holds `b`.
With the bug it receives `b`'s single slot first, followed by `a`'s two slots, and then
encodes them assuming the first two slots belong to the dynamic-type parameter. The length

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the params are (a_offset, a_length, b) and the call site yields a permutation (42, s_offset, s_length), so the offset becomes 42, the length becomes the offset, and the value of b is the length, isn't it? So it would be that the offset field is read from a value type slot, not the length.

@cameel

cameel commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Should we mention that the revert always happens? (it does, doesn't it? just with weird data).

It does say that already, in a way:

The affected code is the construction of revert data for a transaction that is already going to revert, so it has no impact on contract's state.

Because the bug affects only the construction of revert data for transactions that are already going to revert, it does not modify storage, return values, or external calls in the reverting transaction itself.

I wanted to suggest that too at first but in the end decided that the above are already enough. But if you also thought that, maybe there's something to it and we should make that more explicit.

@czepluch
czepluch self-requested a review August 24, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants