📄

Report #12539

Report Date
October 18, 2022

Beanstalk Native DEX (aka Liquidity Wells) Under Development is Susceptible to a Newly Identified Exploitable MEV Strategy that Results in the Theft of User Funds

Report Info

Report ID

#12539

Target

Report type

Smart Contract

Impacts

Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Has PoC?

Yes

Bug Description

Note: this is a revised report submission, following feedback received from the Immunefi team on closed report ID # 12481. This revised report amends the impact and the target, since Liquidity Wells will be a significant update to the Beanstalk smart contract in the near future. Beanstalk's bug bounty page on Immunefi states under the "Assets in Scope" section that "the current implementation and any further updates to the contracts are considered in-scope...If an impact can be caused to any other asset related to Beanstalk that isn’t on this section but for which the impact is in the Impacts in Scope section below, bug bounty hunters are encouraged to submit it for consideration by the BIC."

The Beanstalk Farms development team is currently working on the future Beanstalk Native DEX, otherwise referred to as Liquidity Wells: https://github.com/BeanstalkFarms/Beanstalk/pull/83

Liquidity Wells, as described to Beanstalk users by the Beanstalk Farms development team in various community engagements thus far, will allow for liquidity pools in the Silo to be hosted on Beanstalk natively.

Liquidity Wells will also be permissionless, enabling any user to create a new BEAN pool trading against another token. As such, users will be able to have a yield bearing ERC-20 token representing their shares of the pool.

As described, Liquidity Wells may be susceptible to a newly identified attack vector vis-a-vis an exploitable MEV strategy that results in the theft of all early user deposits, as sent through the public mempool. This exploitable attack vector was recently highlighted on 10/14/22 for Bunni Protocol by Riley Holterhus, a smart contract security expert. As explained by Riley, "This is a variant of a well-known attack, the key difference being the attacker provides liquidity directly to the protocol instead of directly transferring some tokens." Although Bunni Protocol was audited, their auditor explained that they "didn't consider minting liquidity to the contract itself..." (see "References" section below).

Consider a scenario where an innocent user seeks to permissionlessly provide liquidity to a Liquidity Well pool that has never been deposited in before. As detailed by Riley, a malicious MEV searcher can backrun this initial user's transaction with a withdraw call. Since the attacker will then own 100% of the ERC-20 supply corresponding to the pool, they will be given 100% of the liquidity, including the initial deposit from the innocent user. Since the ERC-20 supply would zero out after this, the attacker can continue to repeat this exploit on an unfixed contract.

Impact

Liquidity Wells, upon their debut at the end of Q4 2022 or sometime in early 2023 per recent estimates conveyed by the Beanstalk Farms development team, will host all Silo liquidity for Beanstalk, and will debut the BEAN:ETH pool. Beanstalk's liquidity currently equates to nearly $30M, per the present assets in the BEAN:3CRV Pool, which the Beanstalk Farms team has indicated will be migrated from Curve to Liquidity Wells too.

Beanstalk implements the EIP-2535 Diamond structure, which means it can have multiple upgradable parts. As noted on Beanstalk's Github page, "The Beanstalk smart contract is a multi-facet proxy as it implements EIP-2535, and pulls in functions from a variety of different contracts (called facets in the EIP-2535 documentation) that are all capable of sharing the same state object." See the section "Beanstalk Contract & EIP-2535" here: https://github.com/BeanstalkFarms/Beanstalk

Accordingly, Liquidity Wells will be a substantial update that Beanstalk's smart contract uses as a facet in the near future. As permissionless LP pools will be hosted via Liquidity Wells housed in the Beanstalk smart contract, user funds can be stolen if there is an exploit as outlined in this report. Furthermore, while there is currently a one season withdraw delay from the Silo, if/when this delay is considered for removal in the future as has been discussed at times within the Beanstalk community, then the Beanstalk Farms development team should assess this report's noted MEV attack vector in that decision, where applicable.

Risk Breakdown

Difficulty to Exploit: Easy to Relatively Easy

Weakness: Although Liquidity Wells are not yet live, they are currently under development and will be a significant update to the Beanstalk smart contract. Beanstalk's bug bounty page on Immunefi states that "the current implementation and any further updates to the contracts are considered in-scope."

CVSS2 Score: 4 (although an exploit such as this that can result in the direct theft of user funds would be considered a "Critical" level exploit, I noted the score to correspond with a "High" level exploit since Liquidity Wells are still under development).

Recommendation

As suggested by Riley Holterhus, the smart contract security expert that initially alerted the DeFi community on 10/14/22 about this potential attack vector with regards to Bunni Protocol, "In order to fix this bug, it is recommended to require a minimum number of shares be minted in the first deposit. If the attacker minted 10^18 wei instead of 1 wei at the start, then they would need to supply 10^18 times as much liquidity as the [initial] user, which is infeasible...Another good idea is to revert in the case of minting zero shares because that should never happen anyways."

References

Twitter thread from Riley Holterhus on 10/14/22 outlining this newly identified attack vector: https://twitter.com/rileyholterhus/status/1581028470699982848

Blog post from Riley Holterhus offering more detail about the attack vector and how to address it: https://www.rileyholterhus.com/writing/bunni

Thread from Bunni Protocol auditor detailing that this was an attack vector they did not consider: https://twitter.com/sjkelleyjr/status/1581081068471390208?s=20&t=0AZCgsxV9S7fstw0btfeNQ

Proof of concept

Refer to the blog post by Riley Holterhus, in which he details how such an attack scenario would play out and its proposed fix: https://www.rileyholterhus.com/writing/bunni

See also the fix commit that Riley shared in his referenced Twitter thread for Bunni Protocol: https://github.com/ZeframLou/bunni/commit/a298b105bc963340f56ac7210d98d7f1340fe7fc

BIC Response

Although this submission is related to Beanstalk assets that do not yet exist, the BIC has reviewed the submission in good faith and determined that the bug in question was only possible on Bunni due to the use of Uniswap V3 pools.

In Uniswap V3 pools, anyone is able to provide liquidity on behalf of another user by setting a recipient address at the time of deposit, which is unrelated to the current development direction of Wells. This is feature of Uniswap V3 is pointed out in the article that the hacker shared (https://www.rileyholterhus.com/writing/bunni):

"Calls mint on the underlying Uniswap V3 pool to mint $10,001 worth of liquidity to the Bunni protocol. In Uniswap V3, anyone can provide liquidity on your behalf by setting the recipient address."

This is not functionality that is being pursued in the development of Wells. Because of this, this report is not eligible for a reward.

Reporter Response

The general summary of the reported bug is that the first depositor (the attacker) to a new Liquidity Well pool could manipulate the price of a share to make other early user's deposits round down to zero, such that the attacker can then withdraw and steal all of the deposited tokens in the Liquidity Well pool.

See the following two links noted at the end of the blog post from Riley Holterhus that was cited in the "References" section of the report:

The reported bug is also not exclusive to a DEX employing Uniswap V3 functionality. Rather, the same problem could exist on a DEX following a constant product methodology akin to Uniswap V2 (as Liquidity Wells are expected to do), whereby liquidity providers will receive ERC-20 tokens to represent their share of a respective pool.

In the case of Uniswap V2, the reported bug is prevented by enforcing a minimal initial liquidity to new pools. See lines 120 and 121 from the Uniswap V2 code, which prevent the reported exploit by requiring a "MINIMUM_LIQUIDITY" be sent to the 0 address so it will stay there forever (10 ** 3, per line 15): https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol

The rationale for this minimal initial liquidity requirement is further explained as follows: "If this is the first deposit, create MINIMUM_LIQUIDITY tokens and send them to address zero to lock them. They can never be redeemed, which means the pool will never be emptied completely (this saves us from division by zero in some places)." See: https://ethereum.org/en/developers/tutorials/uniswap-v2-annotated-code/

The justification for this minimal initial liquidity requirement to prevent the reported attack scenario is also explained here: https://ethereum.stackexchange.com/questions/132491/why-minimum-liquidity-is-used-in-dex-like-uniswap

Liquidity Wells should thus enforce a minimal initial liquidity requirement when being launched, to prevent this reported bug from occuring, per the "Recommendation" section of the report. Currently, in the Liquidity Wells facet that is under development, there appears to be no minimal initial liquidity sent to the 0 address. See lines 91 and after (under protocol/contracts/farm/facets/WellFacet.sol), where "Add Liquidty" (typo) is noted: https://github.com/BeanstalkFarms/Beanstalk/pull/83/files

As Liquidity Wells will be permissionless, enabling any Beanstalk user to launch new BEAN pools trading against other tokens, this precaution is especially critical. This is because the BEAN token contract, along with the Liquidity Wells facet once it debuts and is added as an update to the Beanstalk contract, will all be contained within the Beanstalk contract.

As mentioned in the "Impact" section of the report, the Beanstalk smart contract employs the EIP-2535 Diamond standard, enabling it to pull functions from a variety of facets housed within it, and all facets share the same state, thereby increasing the attack surface.

Lastly, in Beanstalk University Class #47, held in the Beanstalk discord on 10/18/22, Publius as one of the founders of Beanstalk mentioned with regards to the oracle development considerations around Liquidity Wells that they've recently come to learn that, "...someone has the potential to manipulate the balance within the [Liquidity] Wells for longer than a block..." This statement reaffirms the applicability of this reported bug report. See: https://www.youtube.com/watch?v=f5aQDshdttI&t=1847s

Ultimately, I have shared this report in good faith and hope that it is beneficial for Beanstalk's ongoing development efforts, and I would appreciate the BIC's reconsideration of its pertinence for Liquidity Wells as a substantive update to the Beanstalk contract that is expected in the coming months.

BIC Response

The implementation for Wells is not finished and the majority of it is going to be rewritten due to architectural changes. Because the implementation is not complete, it also necessarily not yet audited. The BIC deems it best practice to wait until the code is audited in order to consider any rewards. For these reasons, a bounty is not being awarded.

Immunefi Response

Our finding is that this submission don't have any impact of the selected asset. This submission was correctly closed and no reward should be given.

TECHNICAL ASSESSMENT:

Here are some more specifics from our technical assessment of the mediation request. The asset that you've pointed out, Liquidity Wells is out-of-scope as it is still under development process and any bugs at this stage of development are understandable since it wasn't yet audited. Besides, the project may change this asset and it will not affect the end user, therefore there is no impact.

You've also mentioned, that:

The argument that "further updates to the contracts" do not qualify as in-scope unless a BIP is committed is simply disingenuous.

further updates to the contracts means that Beanstalk's contract was already updated, meaning it is useable by the user and can be accessed through the beanstalk diamond proxy. The asset Liquidity Wells was still under development, therefore hasn't been updated to the beanstalk contract and as a result is out-of-scope.

On top of that, the mentioned asset is still in an open PR and hasn't got merged to the master branch https://github.com/BeanstalkFarms/Beanstalk/pull/83/files.