51283 sc critical permanent freeze of user token due to unhandled partial fill refunds for swap via 1inch in dexaggregatorwrapperwithpredicateproxy
Submitted on Aug 1st 2025 at 12:08:18 UTC by @perseverance for Attackathon | Plume Network
Report ID: #51283
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/immunefi-team/attackathon-plume-network-nucleus-boring-vault/blob/main/src/helper/DexAggregatorWrapperWithPredicateProxy.sol
Impacts: Permanent freezing of funds
Description
Short summary
The DexAggregatorWrapperWithPredicateProxy.sol contract is vulnerable to a permanent freeze of user funds when interacting with the 1inch DEX aggregator. If a user initiates a swap using the depositOneInch or depositAndBridgeOneInch function and includes the _PARTIAL_FILL flag in the swap parameters, any unspent token refunded by 1inch is sent back to the proxy contract. The proxy contract has no mechanism to withdraw, unwrap, or transfer this returned token, causing the user's funds to be permanently and irreversibly locked within the contract.
The vulnerability
The core issue is that depositOneInch / depositAndBridgeOneInch do not account for 1inch's partial-fill refund behavior. When _PARTIAL_FILL is set in AggregationRouterV6.SwapDescription, the 1inch router refunds unused source tokens to msg.sender. In this integration, msg.sender is the proxy contract. The proxy:
receives the refunded ERC20 (e.g., WETH),
has no function to unwrap WETH to ETH,
has no generic sweep/transfer for arbitrary ERC20 tokens,
does not forward the refunded token back to the user.
Consequently, refunded tokens remain trapped in the proxy contract permanently.
Relevant contract locations:
Proxy: https://github.com/immunefi-team/attackathon-plume-network-nucleus-boring-vault/blob/main/src/helper/DexAggregatorWrapperWithPredicateProxy.sol
1inch Aggregation router: https://etherscan.io/address/0x111111125421ca6dc452d289314280a0f8842a65#code
Vulnerable excerpt from depositOneInch:
Vulnerable excerpt from _oneInchHelper:
1inch refund logic (relevant excerpt from AggregationRouterV6):
Because the router refunds the unused srcToken to msg.sender (the proxy contract), any unspent WETH / depositAsset is transferred to the proxy and becomes irrecoverable given the proxy's missing recovery/unwrapping logic.
Severity assessment
Bug Severity: Critical
Impact: Permanent freezing of funds. The refunded tokens (e.g., WETH) become permanently trapped in the proxy contract with no recovery mechanism.
Suggested remediation
The function should detect and forward any refunded source token (including WETH) back to the user (or otherwise provide a recovery path). Possible mitigations include:
After the
aggregator.swap(...)call, check the proxy contract's balance of the source token and transfer any excess back to the user.Provide a controlled admin or user-facing sweep/withdraw function for arbitrary ERC20s (with appropriate access controls and safety checks).
If WETH is used, provide an unwrap flow to convert any returned WETH to ETH and refund to the user.
Disallow
_PARTIAL_FILLflag indesc.flagswhen calling 1inch from the proxy if proper handling is not implemented.
Proof of Concept (Conceptual)
This scenario demonstrates the permanent loss of funds.
Sequence diagram (mermaid):
References
1inch Aggregation router contract: https://etherscan.io/address/0x111111125421ca6dc452d289314280a0f8842a65#code
Proxy contract: https://github.com/immunefi-team/attackathon-plume-network-nucleus-boring-vault/blob/main/src/helper/DexAggregatorWrapperWithPredicateProxy.sol
(End of report)
Was this helpful?