HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Front-Running Attack Vector in `AaveDIVAWrapperCore::_removeLiquidity` Due to Non-Atomicity

Summary

The _removeLiquidity function in the AaveDIVAWrapper contract is susceptible to a front-running attack that can prevent users from redeeming their position tokens. While ownership checks mitigate direct theft of funds within the function, an attacker can still exploit the time gap between the token approval and the call to _removeLiquidity to front-run legitimate redemption requests, effectively denying service to the rightful token holders.

Vulnerability Details

A front-running vulnerability exists due to the non-atomic nature of the removeLiquidity process. Approvals for long and short-position tokens occur in a separate transaction from the removeLiquidity call, creating a time window for attackers to observe a user's approval and execute their own removeLiquidity transaction before the legitimate user.

The vulnerability manifests in these lines within _removeLiquidity:

_shortTokenContract.transferFrom(msg.sender, address(this), _positionTokenAmountToRemove);
_longTokenContract.transferFrom(msg.sender, address(this), _positionTokenAmountToRemove);

These lines are not inherently insecure. They are necessary to transfer the tokens. The problem is that they rely on a pre-existing approval granted in a separate transaction. These lines would be secure if the approval were somehow tied to the same atomic transaction as the transfer. However because the approval is separate, an attacker can exploit the time gap.

Attack Path:

  1. Alice approves the AaveDIVAWrapper contract to spend her long and short position tokens. This transaction is broadcast to the mempool.

  2. Bob, a malicious actor, observes Alice's approval transaction in the mempool.

  3. Before Alice's intended removeLiquidity transaction is mined, Bob submits his own transaction that calls the removeLiquidity function (or a wrapper function). Because Alice has already approved the contract, Bob's transaction will be valid.

  4. Bob's transaction is included in a block before Alice's. Bob has now effectively "stolen" Alice's redemption opportunity. Alice's transaction will likely fail, as the tokens are no longer available.

Impact

  • Denial of Service (DoS): The primary impact is a DoS attack. Legitimate users are prevented from redeeming their tokens.

  • Limited Financial Gain: If the attacker has a small amount of the position tokens, they might be able to redeem a small amount of collateral, but this is not the primary risk. The main impact is the DoS.

  • Protocol Reputation Risk: The presence of such vulnerabilities could erode trust in the protocol and deter new users.

Tools Used

Manual Review

Recommendations

The most effective way to mitigate this front-running vulnerability is to tie the approval to the specific redemption request. Here are a few options:

  1. Nonce in Approval: Include a nonce in the approval transaction. This nonce must then be provided as a parameter to the removeLiquidity function (or the calling function). This would tie the approval to a specific redemption request.

  2. Meta-transactions: Use meta-transactions. The user signs a message containing all the details of the withdrawal (including the recipient and the amount) and a relayer submits the transaction on their behalf. This can help protect against front-running because the signed message is only valid for that specific transaction.

  3. Time-Limited Approvals: Approvals should expire after a short period. This limits the window of opportunity for a front-running attack. However, this is less ideal than nonces or meta-transactions, as it requires users to constantly re-approve.

  4. Flashbots (or similar): Use Flashbots or a similar service. This allows users to submit transactions directly to miners, bypassing the mempool. This completely eliminates the possibility of front-running.

  5. Permit Tokens: Use ERC20 tokens that support the permit function (EIP-2612), allowing approvals to be made via a signed message instead of a separate transaction.

    function _removeLiquidity(
    bytes32 _poolId,
    uint256 _positionTokenAmount,
    address _recipient,
    + uint256 deadline,
    + uint8 vShort, bytes32 rShort, bytes32 sShort, // Permit params for shortToken
    + uint8 vLong, bytes32 rLong, bytes32 sLong // Permit params for longToken
    ) internal returns (uint256) {
    // ... rest of _removeLiquidity function (removing liquidity from DIVA, etc.) ...
  6. Approve and RemoveLiquidity in a Single Transaction:

    • Modify the removeLiquidity function to internally handle token approvals. For example, users could pass the approval parameters as part of the same transaction, removing the need for a separate approval step.

Note: The same vulnerability can be found in:

Updates

Lead Judging Commences

bube Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.