During converting through pipelineConvert, it is possible to have negative toStem by manipulating the data when executeAdvancedFarmCalls is called.
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/silo/PipelineConvertFacet.sol#L62
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/silo/PipelineConvertFacet.sol#L98
When converting X amount of token bean to Y LP tokens, during the function call executeAdvancedFarmCalls, it is exepected that X beans will be added as liquidity to the well, and Y LP tokens are returned into the protocol. Regarding the grown stalks, the protocol calculates the amount of grown stalks associated to X amount of beans, and then calculates the toStem as if Y LP tokens produced this amount of grown stalks. The formula for calculating toStem is:
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/libraries/Convert/LibConvert.sol#L523
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/libraries/Silo/LibTokenSilo.sol#L551
The issue is that if during the function call executeAdvancedFarmCalls, the bean amounts added as liquidity to the well is much less than X, the returned LP tokens amount will be much less than Y. But, the protocol still assumes that X beans is converted so the grown stalks associated with X beans will still be included in the calculations.
Thus, if stemTip < (grownstalks associated with X) / (equivalent bdv of small amount of LP tokens), the value of toStem would be negative.
How to manipulate the amount of beans added to the liquidity in the well? In other words how to add small amount of beans as liquidity in the well instead of full X amount?
First X beans are transferred to the C.PIPELINE.
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/libraries/Convert/LibPipelineConvert.sol#L53
Second, executeAdvancedFarmCalls is called that can execute the function advancedPipe in the contract DepotFacet.
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/farm/DepotFacet.sol#L51
This function can execute a series of calls (which are encoded by the user) through the function advancedPipe in the contract Pipeline.
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/pipeline/Pipeline.sol#L61
In this function, the malicious user could encode a function call to add small amount of beans as liquidity to the well instead of full X amounts. By doing so, small amount of LP tokens will be returned to the C.PIPELINE.
The following foundry test shows that the attacker is going to convert 100e6 bean to LP, so the parameter amounts is equal to [100e6]. Thus, during the convert, 100e6 beans are transferred to the C.PIPELINE. But, the created calls beanToLPFarmCalls are as follows in order (Note that these encoded data are inserted as the parameter advancedFarmCalls in the function pipelineConvert):
transfer 100e6 - 10 to the attacker
approve max to the well
add 10 beans as liquidity to the well
By doing so, in reality, only 10 beans are added as liquidity to the well, and as a result 9 bdv of LP tokens are returned. But, since the grownstalks associated with 100e6 beans are considered for calculation of toStem, we have: stemTip < (grownstalks associated with 100e6 beans) / (9). Thus, toStem is negative value equal to -44444436444444. Moreover, it shows that the deposit id is encoded pack of token address + uint96(toStem), since toStem is negative, the uint96 type casting converts the toStem to 0xffffffffffffd793f9274ae4.
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/libraries/LibBytes.sol#L140
The output is:
Negative toStem can have many impacts on the protocol during transfer deposits, withdrawing deposits, depositing enroots, and converting.
It means that the deposit is done in a negative cumulative grown stalks per bdv that does not make sense.
It is recomended to enforce to have non-negative toStem when converting.
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.