Submitted by MiloTruck
The ethPerCvx() function relies on a Chainlink oracle to fetch the CVX / ETH price:
VotiumStrategyCore.sol#L158-L169
The return values from latestRoundData() are validated as such:
VotiumStrategyCore.sol#L173-L181
As seen from above, there is no check to ensure that cl.answer does not go below or above a certain price.
Chainlink aggregators have a built in circuit breaker if the price of an asset goes outside of a predetermined price band. Therefore, if CVX experiences a huge drop/rise in value, the CVX / ETH price feed will continue to return minAnswer/maxAnswer instead of the actual price of CVX.
Currently, minAnswer is set to 1e13 and maxAnswer is set to 1e18. This can be checked by looking at the AccessControlledOffchainAggregator contract for the CVX / ETH price feed. Therefore, if CVX ever experiences a flash crash and its price drops to below 1e13 (eg. 100), the cl.answer will still be 1e13.
This becomes problematic as ethPerCvx() is used to determine the price of vAfEth:
VotiumStrategy.sol#L31-L33
Furthermore, vAfEths price is used to calculate the amount of AfEth to mint to users whenever they call deposit():
AfEth.sol#L162-L166
If CVX experiences a flash crash, vStrategy.price() will be 1e13, which is much larger than the actual price of CVX. This will cause totalValue to become extremely large, which in turn causes amountToMint to be extremely large as well. Therefore, the caller will receive a huge amount of afEth.
Due to Chainlinks in-built circuit breaker mechanism, if CVX experiences a flash crash, ethPerCvx() will return a price higher than the actual price of CVX. Should this occur, an attacker can call deposit() to receive a huge amount of afEth as it uses an incorrect CVX price.
This would lead to a loss of funds for previous depositors, as the attacker would hold a majority of afEths total supply and can withdraw most of the protocols TVL.
Assume the following:
The price of CVX flash crashes from 2e15 / 1e18 ETH per CVX to 100 / 1e18 ETH per CVX. Now, if an attacker calls deposit() with 10 ETH:
As seen from above, the attacker will receive 1e30 AfEth, which is huge compared to the remaining 100e18 held by previous depositors before the flash crash.
Therefore, almost all of the protocols TVL now belongs to the attacker as he holds most of AfEths total supply. This results in a loss of funds for all previous depositors.
Consider validating that the price returned by Chainlinks price feed does not go below/above a minimum/maximum price:
VotiumStrategyCore.sol#L173-L181
This ensures that an incorrect price will never be used should CVX experience a flash crash, thereby protecting the assets of existing depositors.
Asymmetry acknowledged
