CVE-2023-30629: Vyper's raw_call with outsize=0 and revert_on_failure=False returns incorrect success value

Published Apr 24, 2023
·
Updated

Background During the audit of Lido's Gate Seals code statemind team identified a weird behavior of the code that uses rawcall: https://github.com/lidofinance/gate-seals/blob/051593e74df01a4131c485b4fda52e691cd4b7d8/contracts/GateSeal.vy#L164 .

Construction like this: vyper success = rawcall( sealable, abiencode(SEALDURATIONSECONDS, methodid=methodid("pauseFor(uint256)")), revertonfailure=False ) was not fully documented: https://docs.vyperlang.org/en/v0.3.7/built-in-functions.html#rawcall .

The documentation says that: if maxoutsize=0 it should return nothing and then it says that if revertonfailure=False it should return a success flag in the tuple of response, but what if maxoutsize=0 and revertonfailure=False.

<img width="715" alt="image" src="https://user-images.githubusercontent.com/22330612/232125364-d2b3bbac-0b4f-40cb-80ff-f55d8eafef44.png">

So the team started researching what exactly happened in that case, after some research we found that the Vyper compiler generates the wrong bytecode in that case, it generates the sequence: CALL // call MLOAD // MLOAD is wrong since the CALL result is already stored in the stack

Impact Example of buggy code: vyper @external def returnSome(calling: address, a: uint256) -> bool: success: bool = false success = rawcall( calling, abiencode(a, methodid=methodid("a(uint256)")), revertonfailure=False )

any contract that uses the rawcall with revertonfailure=False and maxoutsize=0 receives the wrong response from rawcall. Depending on the memory garbage, the result can be either True or False.

Patches Fix by @charles-cooper https://github.com/vyperlang/vyper/commit/851f7a1b3aa2a36fd041e3d0ed38f9355a58c8ae

Workarounds The simple workaround is always to put maxoutsize>0. Workaround example https://github.com/lidofinance/gate-seals/pull/5/files

References Lido's fix: https://github.com/lidofinance/gate-seals/pull/5/files

Other sources

Vyper is a Pythonic Smart Contract Language for the ethereum virtual machine. In versions 0.3.1 through 0.3.7, the Vyper compiler generates the wrong bytecode. Any contract that uses the rawcall with revertonfailure=False and maxoutsize=0 receives the wrong response from rawcall. Depending on the memory garbage, the result can be either True or False. A patch is available and, as of time of publication, anticipated to be part of Vyper 0.3.8. As a workaround, one may always put maxoutsize>0.

Affected Software

2 affected componentsFixes available
pip/vyper>=0.3.1<0.3.8
0.3.8
vyperlang vyper>=0.3.1<0.3.8

Event History

Apr 24, 2023
CVE Published
via MITRE·09:58 PM
Data Sourced
via MITRE·09:58 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·10:33 PM

Frequently Asked Questions

1

What is CVE-2023-30629?

CVE-2023-30629 is a vulnerability in the Vyper compiler that generates the wrong bytecode.

2

What is Vyper?

Vyper is a Pythonic Smart Contract Language for the Ethereum virtual machine.

3

Which versions of Vyper are affected by CVE-2023-30629?

Versions 0.3.1 through 0.3.7 of Vyper are affected by CVE-2023-30629.

4

What impact does CVE-2023-30629 have?

CVE-2023-30629 can cause contracts that use the `raw_call` function with specific parameters to receive incorrect responses.

5

How can I fix CVE-2023-30629?

To fix CVE-2023-30629, update Vyper to version 0.3.8 or higher.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203