Beanstalk Notion
Beanstalk Notion
/
🪲
Bug Reports
/
BIC Notes
/
📄
Report #31737
📄

Report #31737

Report Date
May 26, 2024
Status
Closed
Payout

Critical Vulnerability Chain Allows Illegitimate Minting of LP Tokens in Beanstalk Wells

‣
Report Info

Report ID

#31737

Report type

Smart Contract

Has PoC?

Yes

Target

https://etherscan.io/address/0xBA510e11eEb387fad877812108a3406CA3f43a4B

Impacts

Illegitimate minting of protocol native assets

Description

A critical vulnerability chain exists in the interaction between the MultiFlowPump and WellImplementation contracts within the Beanstalk protocol, potentially allowing an attacker to mint an unlimited amount of LP tokens. This arises from a lack of input validation in MultiFlowPump, enabling manipulation of geometric mean oracles, coupled with flawed logic in the sync function of WellImplementation. Successful exploitation could lead to severe economic damage, devaluing existing LP tokens and potentially allowing the attacker to drain Well assets.

Vulnerability Details

Two primary weaknesses contribute to this vulnerability:

1. Lack of Validation in MultiFlowPump.update:

  • The update function in MultiFlowPump ([https://etherscan.io/address/0xBA510f10E3095B83a0F33aa9ad2544E22570a87C#code#F1#L72](https://etherscan.io/address/0xBA510f10E3095B83a0F33aa9ad2544E22570a87C#code#F1#L72)) accepts an array of reserves without enforcing a minimum value for each reserve.
  • This allows an attacker to call update with reserve values of zero or near-zero.

2. Flawed Logic in Well.sync:

  • The sync function ([https://etherscan.io/address/0xBA510e11eEb387fad877812108a3406CA3f43a4B#code#F1#L392](https://etherscan.io/address/0xBA510e11eEb387fad877812108a3406CA3f43a4B#code#F1#L392)) calculates newTokenSupply based on potentially manipulated reserves from the MultiFlowPump oracles.
  • If newTokenSupply exceeds the oldTokenSupply, new LP tokens are minted without considering the validity of the underlying reserves.

Exploit Chain:

  1. Reserve Manipulation: An attacker manipulates a Well's reserves to become very low, potentially exploiting other vulnerabilities or through market actions.
  2. Manipulating the Oracle: They call update on the Well's MultiFlowPump with these low or zero reserves. This sets the Pump's geometric mean oracles to near-zero or zero values.
  3. Triggering sync: The attacker (or even an unsuspecting user) calls sync on the Well.
  4. Illegitimate Minting: sync calculates a massively inflated newTokenSupply due to the manipulated oracles, resulting in minting a vast amount of LP tokens, primarily distributed to the attacker.

Impact Details

This vulnerability is classified as High Impact per the Beanstalk bug bounty program ([https://immunefi.com/bug-bounty/beanstalk/](https://immunefi.com/bug-bounty/beanstalk/)), as it enables Illegitimate minting of protocol-native assets. The impact includes:

  • Severe LP Token Dilution: Illegitimate LP token minting significantly devalues holdings of legitimate liquidity providers.
  • Potential Well Drain: With a controlling stake of LP tokens, the attacker could drain the Well of its underlying assets, leading to significant financial losses.
  • Loss of Trust and Reputation: A successful exploit would severely damage Beanstalk's reputation and user confidence.

References

  • MultiFlowPump contract: [https://etherscan.io/address/0xBA510f10E3095B83a0F33aa9ad2544E22570a87C#code](https://etherscan.io/address/0xBA510f10E3095B83a0F33aa9ad2544E22570a87C#code)
  • WellImplementation contract (implemented by Well): [https://etherscan.io/address/0xBA510e11eEb387fad877812108a3406CA3f43a4B#code](https://etherscan.io/address/0xBA510e11eEb387fad877812108a3406CA3f43a4B#code)
  • Beanstalk Bug Bounty Program: [https://immunefi.com/bug-bounty/beanstalk/](https://immunefi.com/bug-bounty/beanstalk/)

Proof of concept

This POC can be conducted on a local environement of using the tools of your choice

Contracts:

  • ExploitMultiFlow.sol:

Steps:

  1. Deployment:
    • Deploy MultiFlowPump.
    • Deploy a Well contract (Well in this case), setting the deployed MultiFlowPump as its Pump during deployment.
    • Fund the Well with initial liquidity (e.g., 1000 of each token).
    • Deploy the ExploitMultiFlow contract, providing the addresses of the deployed MultiFlowPump and Well.
  2. Fund Attacker: Fund ExploitMultiFlow contract with sufficient ETH.
  3. Execute Exploit:
    • Call the exploit function on ExploitMultiFlow.
    • Pass an array manipulatedReserves where at least one of the Well's reserve values is set to zero or a very low number. For example, if the Well has two tokens, manipulatedReserves = [1, 0] would set the second reserve to zero.
  4. Observe Results:
    • Check the ExploitMultiFlow contract's balance of LP tokens. It should have increased significantly due to illegitimate minting.
    • Observe the Well's reserves using getReserves. They should be very low or drained.
    • Check the Well's total LP token supply. It should be vastly inflated compared to the legitimate liquidity initially provided.

Immunefi Response

We have reviewed your submission, but unfortunately, we are closing the report for the following reasons:
  • The submission contains the output of an automated scanner without demonstrating that it is a valid issue.
  • The submission lacks the required information regarding the vulnerability's impact on the reported asset.

As per the bug bounty program's policy, we require all submissions to be accompanied by a Proof of Concept (PoC) that demonstrates the vulnerability's existence and impact. Since the submission doesn't provide any proof of the vulnerability's existence, we have decided to close it.

Please note that the project will receive a report of the closed submission and may choose to re-open it, but they are not obligated to do so.

pragma solidity ^0.8.0;

interface IMultiFlowPump {
    function update(uint256[] calldata reserves, bytes calldata data) external;
}

interface IWell {
    function sync(address recipient, uint256 minLpAmountOut) external returns (uint256 lpAmountOut);
    function getReserves() external view returns (uint256[] memory);
}

contract ExploitMultiFlow {
    IMultiFlowPump public immutable multiFlowPump;
    IWell public immutable well;

    constructor(address _multiFlowPump, address _well) {
        multiFlowPump = IMultiFlowPump(_multiFlowPump);
        well = IWell(_well);
    }

    function exploit(uint256[] memory manipulatedReserves) external {
        // Manipulate reserves in MultiFlowPump (set to near-zero or zero)
        multiFlowPump.update(manipulatedReserves, "");
        // Trigger sync to mint illegitimate LP tokens
        well.sync(address(this), 0);
    }
}