CVE-2024-32649
Executive Summary
CVE-2024-32649 is a low-severity vulnerability in the Vyper smart contract language (versions 0.3.10 and prior) affecting the sqrt built-in function. The flaw arises from a double evaluation of the argument when it contains side-effects, due to the build_IR function not caching the argument to the stack. This can lead to unexpected behavior in contracts that rely on deterministic execution, though no vulnerable production contracts have been identified. The EPSS score is 0.0%, indicating minimal active exploitation risk. No patch is currently available, but the impact is limited to edge cases in development or testing environments.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Vyper is a Python-based smart contract language for Ethereum. This vulnerability affects the compiler itself, not a package manager distribution. Developers using Vyper should monitor the official repository for future patches and avoid using sqrt with arguments that have side-effects in production contracts.
CVSS Breakdown & Threat Level
- CVSS Score: 5.3 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: None
- Integrity Impact: None
- Availability Impact: Low
The low availability impact reflects the difficulty of exploiting this in practice, as it requires specific side-effect patterns in contract code.
Deep Dive & Mechanics
The sqrt built-in in Vyper computes the square root of a given value. In vulnerable versions, the build_IR function does not cache the argument to the stack before evaluation. This means that if the argument is an expression with side-effects (e.g., a function call that modifies state), it will be evaluated multiple times during the IR generation process. This can lead to:
- State inconsistency: The same side-effect may execute more than once, altering contract state unexpectedly.
- Gas cost inflation: Repeated evaluations increase gas consumption.
- Logic errors: Contracts relying on deterministic behavior may produce incorrect results.
The vulnerability is rooted in the compiler's intermediate representation (IR) generation, not in runtime execution. It only affects contracts compiled with vulnerable compiler versions.
Vulnerable vs. Patched Code
Vulnerable Code (Vyper <= 0.3.10):
# In the compiler's sqrt built-in implementation
def build_IR(self, expr, context):
# No caching of argument to stack
arg = expr.args[0]
# arg is evaluated multiple times in subsequent IR generation
return [
["if", ["lt", arg, 0], ...], # First evaluation
["sqrt", arg], # Second evaluation
]
Patched Code (Hypothetical fix):
def build_IR(self, expr, context):
# Cache argument to stack to prevent double evaluation
arg = expr.args[0]
cached_arg = ["mstore", ["add", "mload", 0x40], arg] # Cache to memory
return [
cached_arg,
["if", ["lt", ["mload", ["add", "mload", 0x40]], 0], ...],
["sqrt", ["mload", ["add", "mload", 0x40]]],
]
The fix ensures the argument is evaluated once and stored, then referenced from the stack or memory.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Vyper compiler version 0.3.10 or earlier
- A smart contract using
sqrtwith a side-effect argument
Exploitation Steps:
- Create a Vyper contract with a state-modifying function used as argument to
sqrt:@external def vulnerable_function(x: uint256) -> uint256: return sqrt(self.update_state(x)) # update_state has side-effects - Compile with vulnerable compiler version.
- Deploy to a testnet or local Ethereum environment (e.g., Ganache).
- Call
vulnerable_functionand observe thatupdate_stateexecutes twice, leading to double state changes.
Expected Outcome: The contract's state is modified twice per call, causing inconsistency.
Blue Team
Detection:
- Review all Vyper contracts for use of
sqrtwith non-constant arguments. - Use static analysis tools to detect potential double evaluation patterns.
- Monitor contract state changes for unexpected increments.
Mitigation:
- Avoid using
sqrtwith arguments that have side-effects until a patch is available. - Upgrade to a patched compiler version when released.
- Implement manual caching in contract code:
@external def safe_function(x: uint256) -> uint256: cached = self.update_state(x) return sqrt(cached)
Indicators of Compromise (IOCs)
- Compiler Version: Vyper <= 0.3.10
- Contract Bytecode Pattern: Look for
sqrtopcode usage in bytecode where the argument is not preceded by aDUPorMLOADinstruction. - Transaction Anomalies: Repeated state changes in a single transaction where
sqrtis called.
Detection Engineering
YARA Rule
rule Detect_Vyper_Sqrt_Double_Eval {
meta:
description = "Detects Vyper bytecode with potential sqrt double evaluation"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-32649"
strings:
$sqrt_opcode = { 14 } // EVM SQRT opcode
$no_cache_pattern = { 14 (?!.*(80|51)) } // SQRT without preceding DUP or MLOAD
condition:
$sqrt_opcode and #no_cache_pattern > 0
}
Sigma Rule
title: Vyper Sqrt Double Evaluation Detection
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects potential exploitation of CVE-2024-32649 in Vyper contracts
author: Valters IT
logsource:
category: ethereum
product: transaction
detection:
selection:
contract_bytecode|contains: '14' # SQRT opcode
condition: selection
falsepositives:
- Legitimate use of sqrt with constant arguments
level: low
Suricata Rule
alert ip any any -> any any (
msg:"CVE-2024-32649 Vyper Sqrt Double Evaluation Attempt";
content:"|14|"; offset:0; depth:1;
reference:cve,2024-32649;
classtype:attempted-recon;
sid:1000001;
rev:1;
)
Remediation & Mitigation
- Immediate: Avoid using
sqrtwith arguments that have side-effects in Vyper contracts. - Short-term: Manually cache the argument before passing to
sqrt:cached_val = self.side_effect_function() result = sqrt(cached_val) - Long-term: Upgrade to a patched version of the Vyper compiler once released. Monitor the official Vyper GitHub repository for updates.
- Detection: Implement static analysis in CI/CD pipelines to flag
sqrtusage with non-constant arguments.
Valters IT signature: This report is generated for educational and defensive purposes. Always verify with official sources.