Lucene search

K
code423n4Code4renaCODE423N4:2023-08-DOPEX-FINDINGS-ISSUES-2196
HistorySep 06, 2023 - 12:00 a.m.

the perpetualVaultLP.sol is vulnable by flashloan attack

2023-09-0600:00:00
Code4rena
github.com
8
perpetualatlanticvaultlp
flash loan
deposit function
redeem function
security vulnerability
rdpx tokens

6.8 Medium

AI Score

Confidence

High

Lines of code
<https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVaultLP.sol#L145-L175&gt;

Vulnerability details

impact

The perpVaultLp contract is susceptible to a flash loan attack. An attacker can exploit the vulnerability by executing flash loan transactions using both the deposit() and redeem() functions. This allows the attacker to acquire extra rdpx tokens and increase their share of assets within seconds, all without actually adding a balance to the perpVaultLP. The attacker only needs to obtain a flash loan of weth as the deposit asset, and then they can use the deposit function to mint shares and subsequently call the redeem function to receive the flash loan amount along with additional rdpx tokens.

proof of concepts

The deposit function allows users to deposit assets (weth or rdpx) into the perpVaultLp contract. Since this function is public and accessible to any users, it can be exploited by an attacker. Here’s a portion of the deposit function:

function deposit(
        uint256 assets,
        address receiver
    ) public virtual returns (uint256 shares) {
        // Check for rounding error since we round down in previewDeposit.
        require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");

        perpetualAtlanticVault.updateFunding();

        // Need to transfer before minting or ERC777s could reenter.
        collateral.transferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

        _totalCollateral += assets;

        emit Deposit(msg.sender, receiver, assets, shares);
    }

The redeem function allows users to redeem their assets by burning their shares and receiving extra rdpx tokens.

 function redeem(
        uint256 shares,
        address receiver,
        address owner
    ) public returns (uint256 assets, uint256 rdpxAmount) {
        perpetualAtlanticVault.updateFunding();

        if (msg.sender != owner) {
            uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.

            if (allowed != type(uint256).max) {
                allowance[owner][msg.sender] = allowed - shares;
            }
        }
        (assets, rdpxAmount) = redeemPreview(shares);

        // Check for rounding error since we round down in previewRedeem.
        require(assets != 0, "ZERO_ASSETS");

        _rdpxCollateral -= rdpxAmount;

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        collateral.transfer(receiver, assets);

        IERC20WithBurn(rdpx).safeTransfer(receiver, rdpxAmount);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);
    }

in this case an attacker can:
Use a contract to obtain a substantial amount of weth through a flash loan.

Call the deposit function to update the _totalCollateral and mint shares corresponding to their weth balance.

In the same transaction, call the redeem function to redeem the weth, essentially paying back the flash loan. Simultaneously, the attacker receives an amount of rdpxAmount.

This attack can have a substantial impact as it effectively causes the protocol to grant the attacker a large quantity of rdpx tokens without any meaningful contribution.

Tools used

manual review

recommendation

I recommend implementing a delay mechanism for the deposited amount or restricting access to the deposit function to whitelist addresses only. These measures can help mitigate flash loan attacks and protect the protocol from such exploits

Assessed type

Other


The text was updated successfully, but these errors were encountered:

All reactions

6.8 Medium

AI Score

Confidence

High