It is possible to advance multiple seasons if enough time passes. That can lead to serious problems for the protocol
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#L79-L84
It is possible to advance multiple seasons if enough time has passed. That can lead to some issues that can be exploited in the protocol.
Issue nº1:
Beanstalk was previously hacked due to a governance attack powered by a flashloan. The hacker was able to get enough voting power (stalk) to unilaterally drain all funds. This was possible because when someone deposited into the silo he got the corresponding amount of stalk in the same transaction. After this event, the Beanstalk team changed that to prevent flashloan attacks by putting in a germinating state to stalk that new deposits would mint. With this state, the user will not get immediately the stalk and a flashloan attack would be impossible to execute because it needs to be done in the same transaction. This germinating state requires to pass 2 seasons in order to claim the stalk that has already germinated. Seasons are meant to be 1 hour long so it would take 2 hours to claim the stalk. However, if enough time elapses it is possible to advance multiple seasons in the same transaction.
Let's first look closely at the sunrise
function:
The seasonTime
function returns the current timestamp minus the timestamp when the protocol either started or unpaused in case it was paused at some point. Hence the time elapsed from the beggining divided by the period which should be 1 hour. This is the theorical amount of season that should have passed if the sunrise function whould have been called exactly when an hour would have passed. The require statement ensures that this amount is greater than the current season number. This means that if for example 2 hours passed before the last sunrise call, it is possible to call the sunrise function 2 times in the same transaction.
Since the flashloan protection consists in 2 season germination for the stalk, it means that it can be bypassed by anyone when more than 2 hours passed without calling the sunrise function. This event can happen for a lot of factors:
Blockchain outrage (considering it will be migrated to an L2)
Block stuffing
Normal users not calling sunrise function
If this event happens someone can just take a flashloan, deposit into the silo, call the sunrise function twice and get all the stalk immediately proportional to the flashloan.
Proof of concept:
The following test uses the silo.t.sol
setup.
Result:
As we can see, the user got stalk immediately without any germination because more than a single season elapsed. This break the flashloan protection because a user can take a flashloan and get a huge amount of stalk in the same transaction. With this stalk, he can propose BIP or redeem them for beans.
Issue nº2:
When updating the oracle in the sunrise
function, the price fetched from the twaDeltaB
will be instantaneous and will not be actually time weighted which can lead to manipulations.
The s.sys.season.timestamp
is the saved timestamp that gets updated when the oracle has computed the delta B. But when 2 seasons get executed in the same transaction, the second one will compute the substraction of the block.timestamp
minus the s.sys.season.timestamp
that will have the same value because it has been saved in the same transaction. This will result to 0 and will be used as lookback to fetch the delta B from wells.
Medium, the scenario where the sunrise function is not called for more than 2 hours can be pretty rare but a user could leverage this moment to get a lot of benefit with a flashloan or to manipulate the price and get benefit from the manipulated delta B. Medium risk should be good for it.
Manual review
I would only allow to call the sunrise function once at a time even when a lot of time passed since the last sunrise call. That would disable this attack and all other components that rely on the season number. Right now all the components that depend on the season number can be manipulated by this same attack when a halting happens for any reason.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.