On March 6, 2025, 1inch Network, one of DeFi's leading DEX aggregators, disclosed a $5 million exploit targeting resolvers using the deprecated Fusion v1 contract. The attacker exploited a low-level calldata corruption vulnerability to impersonate legitimate resolvers, swapping minimal wei for millions in user tokens across multiple transactions.
This wasn't a logic error or a business logic flaw. It was precision exploitation of EVM-level memory handling, weaponizing the gap between how Solidity appears to work and how the EVM actually executes bytecode. The vulnerability had survived multiple audits because it required understanding assembly-level calldata manipulation, buffer boundaries, and signed versus unsigned integer comparison semantics — precisely the type of low-level issue that pattern-based auditing misses but deterministic analysis catches.
Following negotiations between 1inch, affected resolvers, and the attacker, the majority of stolen funds were returned minus a "bug bounty" fee. The attack could have been prevented entirely with proactive security measures that detect calldata handling vulnerabilities before deployment.
The Attack: Forging Resolver Identity Through Memory Manipulation
The exploit weaponized a buffer overflow in the _settleOrder function to corrupt memory and forge resolver addresses. By carefully crafting transaction calldata length, the attacker manipulated how the contract parsed serialized order data, allowing them to substitute their own address in place of legitimate resolvers.
Preparation Phase: Mapping the Memory Layout
The attacker needed to understand the precise memory layout of the Settlement contract's order processing:
- How calldataload operations read order data from transaction calldata
- Where the interactionLength variable determined the location of the order suffix containing the resolver address
- How buffer boundaries could be exceeded through carefully sized transactions
- Which calldata offsets would allow injection of a forged order suffix
This required reverse-engineering the contract's serialization format and identifying the exact transaction size that would trigger the overflow without causing an immediate revert.
Atomic Execution: The Invisible Substitution
Once calibrated, the attacker executed the exploit through these steps:
1. Transaction Size Manipulation: Craft an unusually long transaction that exceeds expected buffer boundaries, triggering an overflow of the interactionLength variable used to calculate memory offsets
2. Offset Corruption: The overflowed interactionLength value feeds into an unsafe calculation that determines where the order suffix (containing the resolver address) is located in the serialized calldata
3. Address Injection: With the corrupted offset, the contract reads the resolver address from an attacker-controlled portion of calldata rather than the legitimate location, effectively allowing the attacker to provide their own order suffix
4. Privilege Escalation: Now masquerading as the legitimate resolver, the attacker executes swaps with resolver privileges, trading negligible amounts (a few wei) for millions in tokens
5. Fund Extraction: Execute multiple swaps within single transactions, draining $2.4M USDC and 1,276 WETH before the vulnerability is discovered
The attack targeted resolvers still running Fusion v1, which had been deprecated since 2023 but remained in production for backward compatibility. The code was never self-destructed, creating a persistent attack surface that the attacker exploited systematically.
The Root Cause: Unsigned Comparison After Calldata Load
At the heart of the exploit was improper handling of values after calldataload operations in the Settlement contract's _settleOrder function. The vulnerability exists at line 118, where value checks following calldataload used unsigned comparison operations instead of signed operations.
In the _settleOrder function, after loading data from calldata, the contract performs bounds checking to validate that offsets and lengths fall within expected ranges. However, these checks used unsigned comparisons (lt/gt opcodes) rather than signed comparisons (slt/sgt opcodes).
This distinction is critical in EVM execution:
// Conceptual representation of the vulnerable pattern
function _settleOrder(bytes calldata orderData) internal {
uint256 interactionLength;
assembly {
interactionLength := calldataload(offset)
}
// Vulnerable: Using unsigned comparison
// If interactionLength overflows, it wraps to a large positive number
// This passes the check even though the value is corrupted
require(interactionLength < MAX_LENGTH, "Invalid length");
// This calculation now uses the corrupted value
uint256 suffixOffset = baseOffset + interactionLength;
// Reads resolver address from wrong location
address resolver = _parseResolverAddress(suffixOffset);
}
When interactionLength overflows due to the buffer overflow, it wraps around to a large positive value. Unsigned comparison treats this as a valid large number, passing bounds checks that should have failed. The corrupted value then feeds into offset calculations that determine where the resolver address is read from in the serialized order data.
Why Signed Comparison Matters
Signed comparison (slt/sgt) would have interpreted the overflowed value as a negative number, correctly failing the bounds check:
// Secure pattern: Using signed comparison
assembly {
interactionLength := calldataload(offset)
// With signed comparison, overflow produces negative value
// Bounds check fails, preventing exploitation
if sgt(interactionLength, MAX_LENGTH) {
revert(0, 0)
}
}
The attacker exploited this distinction by:
- Overflowing interactionLength through precisely sized transaction calldata
- Having the corrupted value pass unsigned comparison checks
- Using the corrupted offset to point to attacker-controlled calldata
- Injecting a forged order suffix with their own resolver address
This allowed complete bypass of resolver authentication, enabling unauthorized fund transfers.
What Olympix Found: Lt/Gt After CalldataLoad
Olympix's static analysis detected this exact vulnerability in the Settlement contract before the exploit occurred.
Vulnerability: Lt/Gt After CalldataLoad Severity: Medium Location: Settlement.sol:118 False Positive: No
Finding Description: "After doing a calldataload the value checks should be done with signed version of lesser/greater than. slt and sgt otherwise it can lead to unintended bytes manipulation."
This finding demonstrates the precision of deterministic analysis. Olympix identified:
- The exact line where the vulnerability exists (Settlement.sol:118)
- The specific pattern: value checks after calldataload using unsigned comparison
- The concrete remediation: use slt/sgt instead of lt/gt
- The security impact: enables unintended bytes manipulation
This wasn't a vague warning about "potential issues with memory handling" or "consider reviewing calldata operations." It was a surgical identification of the exact operation, at the exact location, with the exact fix required.
How This Could Have Been Prevented
The Olympix finding demonstrates that automated low-level analysis could have identified the vulnerability pattern before deployment.
Pre-Deployment Detection
Olympix's static analysis specifically flagged the unsigned comparison after calldataload at line 118. This type of vulnerability is extremely difficult to catch in traditional audits because:
It operates at the EVM opcode level: Auditors reviewing Solidity code may not trace through to the actual assembly operations and comparison opcodes used It appears safe at first glance: Bounds checking is present, but using the wrong comparison type It requires adversarial edge cases: The vulnerability only manifests when an attacker intentionally overflows the value through precisely calibrated transaction size Testing rarely covers it: Standard test suites don't include adversarial calldata fuzzing to find buffer overflow triggers
Automated analysis can systematically detect these patterns by:
- Analyzing compiled bytecode, not just Solidity source
- Identifying all calldataload operations and subsequent comparison opcodes
- Flagging mismatches between signed and unsigned comparisons in security-critical contexts
- Understanding EVM semantics around integer overflow and wraparound behavior
Targeted Remediation
With this finding, developers could have:
Implemented signed comparisons: Replace lt/gt with slt/sgt after all calldataload operations involving bounds checks:
assembly {
let length := calldataload(offset)
// Use signed comparison to catch overflow
if sgt(length, MAX_SAFE_LENGTH) {
revert(0, 0)
}
}
Added overflow guards: Implement explicit overflow detection before using loaded values in calculations:
assembly {
let length := calldataload(offset)
// Check for overflow explicitly
if gt(length, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
revert(0, 0) // Value too large, likely overflow
}
}
Bounded buffer operations: Validate that all offset calculations remain within safe memory boundaries:
function _settleOrder(bytes calldata orderData) internal {
require(orderData.length < MAX_ORDER_SIZE, "Order too large");
uint256 suffixOffset = baseOffset + interactionLength;
require(suffixOffset < orderData.length, "Offset out of bounds");
require(suffixOffset + SUFFIX_SIZE < orderData.length, "Suffix exceeds bounds");
}
Restricted deprecated code: Self-destructed Fusion v1 contracts or implemented circuit breakers preventing their use in production environments
The Fix That Would Have Worked
The core issue was using unsigned comparison semantics in security-critical bounds checking after calldataload. The fix would have been straightforward:
// Vulnerable pattern in Settlement.sol:118
assembly {
let length := calldataload(lengthOffset)
// WRONG: Unsigned comparison
// Overflowed values pass this check
if gt(length, maxLength) {
revert(0, 0)
}
}
// Secure pattern
assembly {
let length := calldataload(lengthOffset)
// CORRECT: Signed comparison
// Overflowed values are negative, fail check
if sgt(length, maxLength) {
revert(0, 0)
}
// Additional safety: Explicit overflow detection
if gt(length, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
revert(0, 0)
}
}
This single change — using sgt instead of gt — would have prevented the entire attack vector. The overflowed interactionLength would have been interpreted as a negative value, failing the bounds check and reverting before the corrupted offset could be used.
Why Traditional Audits Missed This
This exploit reveals fundamental limitations of traditional security approaches in catching low-level EVM vulnerabilities.
Audits Focus on High-Level Logic
Multiple top-tier audit firms reviewed the Fusion v1 code. But traditional audits primarily analyze:
- Business logic correctness
- Access control patterns
- Known vulnerability patterns (reentrancy, oracle manipulation, etc.)
- Token accounting and arithmetic errors
They rarely dive into:
- Assembly-level calldata handling
- Opcode-level comparison semantics
- Buffer overflow conditions in serialized data parsing
- Signed versus unsigned integer interpretation in bounds checking
An auditor reviewing Settlement.sol would see bounds checking after calldataload and likely consider it adequately protected. Understanding that unsigned comparison allows overflow wraparound to bypass these checks requires EVM-level analysis that most auditors don't perform systematically.
The Vulnerability Hides in Plain Sight
The vulnerable code doesn't look obviously wrong:
// This appears to be proper bounds checking
require(interactionLength < MAX_LENGTH, "Invalid length");
// This appears to be safe offset calculation
uint256 suffixOffset = baseOffset + interactionLength;
The vulnerability only emerges when you understand:
- How calldataload can be manipulated through transaction size
- How integer overflow affects comparison results
- How unsigned vs. signed comparisons interpret overflowed values differently
- How the corrupted offset enables forging resolver addresses
This requires tracing through assembly execution, understanding EVM integer semantics, and thinking adversarially about how an attacker would craft inputs to trigger overflow conditions. Manual reviewers would need to:
- Decompile or review assembly code
- Map calldata layout and parsing logic
- Identify overflow trigger conditions
- Trace corrupted values through offset calculations
- Understand the security implications of address substitution
This level of low-level, cross-component analysis is precisely what automated tools excel at.
Testing Doesn't Catch EVM-Level Edge Cases
Even comprehensive test suites struggle with these vulnerabilities because:
Standard tests use normal inputs: Test transactions have reasonable sizes and don't deliberately trigger buffer overflows
Fuzzing may miss precise triggers: Random input generation is unlikely to hit the exact transaction size needed to overflow interactionLength while still passing other validation
Integration tests focus on happy paths: Tests verify that legitimate resolvers can process orders correctly, not that attackers can forge resolver identities
Assembly behavior is opaque: Without explicitly testing signed vs. unsigned comparison semantics, the difference is invisible in test results
The attacker essentially performed adversarial fuzzing to discover the exact calldata structure that would:
- Trigger the overflow
- Pass all other validation checks
- Corrupt the offset to the desired value
- Enable address substitution
Standard test suites don't include this level of adversarial exploration.
The Broader Lesson: Deprecation Isn't Security
The 1inch exploit proves that backward compatibility can be a security liability. A deprecated contract continued running in production for years after being marked unsupported, creating a persistent attack surface that eventually resulted in a $5 million loss.
Why Deprecation Failed as a Security Control
No Hard Cutoff: Fusion v1 was deprecated in 2023 but never disabled. Resolvers could continue using it indefinitely, accumulating technical debt with no forcing function to upgrade.
Split Responsibility: 1inch deprecated the protocol, but third-party resolvers were responsible for migrating. This diffusion of responsibility meant vulnerable contracts stayed in production long after better versions existed.
Backward Compatibility Over Security: The decision not to self-destruct Fusion v1 prioritized backward compatibility over eliminating the attack surface. This is a common trade-off in DeFi, and this incident demonstrates its risks.
No Monitoring of Deprecated Code: Because Fusion v1 was officially unsupported, it likely received less security attention than active protocols, even though it still processed real value.
What V2 Got Right
Fusion v2 was completely unaffected by this attack. While the specific calldata corruption vulnerability may have been fixed, the broader lesson is about security-first development:
Proper Calldata Handling: Using safe deserialization patterns and appropriate comparison operations
Updated Assembly Patterns: Following best practices for low-level memory operations and bounds checking
Active Maintenance: Being the supported, actively maintained version meant any discovered vulnerabilities would be patched promptly
The incident validates that protocol upgrades aren't just about adding features — they're about eliminating accumulated security debt.
Looking Forward: The Case for Low-Level Analysis
The 1inch exploit demonstrates a harsh reality: high-level audits can't catch low-level vulnerabilities. The industry needs security tools that understand EVM execution semantics, not just Solidity syntax.
What Protocols Need Now
EVM-Level Analysis: Security tools must analyze compiled bytecode, not just source code, to catch opcode-level vulnerabilities
Assembly Pattern Detection: Systematically identify unsafe patterns in inline assembly, especially around calldata handling, memory operations, and comparison semantics
Adversarial Edge Case Testing: Test with inputs designed to trigger buffer overflows, integer wraparound, and other boundary conditions
Deprecation Enforcement: When code is deprecated, either self-destruct it or implement circuit breakers. Don't leave attack surfaces active indefinitely.
Continuous Monitoring: Even deprecated code should be monitored if it's still processing value in production
What Olympix Provides
Olympix's approach combines:
Bytecode-Level Static Analysis: Examining compiled contracts to detect opcode-level vulnerabilities that aren't visible in Solidity source
Signed/Unsigned Comparison Detection: Systematically identifying mismatches between comparison types in security-critical contexts
Calldata Manipulation Analysis: Detecting unsafe patterns in how contracts parse and validate transaction calldata
Buffer Overflow Detection: Identifying unsafe offset calculations and memory access patterns that could be exploited through crafted inputs
Pre-Deployment Prevention: Catching these vulnerabilities during development, not after millions are drained
The Olympix finding on Settlement.sol:118 demonstrates this precision. Not a vague warning. Not a "consider reviewing." A specific line, a specific pattern, a specific fix.
Conclusion
The 1inch Fusion v1 exploit shows how low-level EVM vulnerabilities can hide in plain sight, survive multiple audits, and eventually cost millions. A single incorrect comparison operation — gt instead of sgt — enabled attackers to forge resolver identities and drain $5 million.
Olympix's pre-exploit analysis identified the exact vulnerability at the exact location with the exact remediation required. This finding demonstrates that automated low-level analysis can detect the subtle, opcode-level vulnerability patterns that lead to real-world exploits.
Traditional audits focus on business logic and known attack patterns. But the next major exploit won't look like the last one. It will be a novel abuse of EVM semantics that appears safe at the Solidity level but becomes exploitable at the bytecode level. Automated analysis can find these patterns by systematically examining how the EVM actually executes code under adversarial conditions.
Low-level vulnerabilities exist in production code right now, hiding in assembly blocks and opcode-level operations. The only question is whether protocols will find them before attackers do.
Don't let EVM-level vulnerabilities drain your protocol. Olympix's automated security analysis catches calldata manipulation, buffer overflow, and comparison semantic vulnerabilities before deployment.
Olympix: Your Partner in Secure Smart Contracts
Olympix provides advanced Solidity analysis tools to help developers identify and fix vulnerabilities before they become critical exploits.
Get started today to fortify your smart contracts and proactively shield them from exploits in the evolving Web3 security landscape.
Connect with us on:
Twitter | LinkedIn | Discord | Medium | Instagram | Telegram | Newsletter