-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eeyore - Corrupted oracle system if more than 2 underlying tokens are used and one of them is WSTETH #266
Comments
actualAmounts
via target ratios based on token amounts is wrong.
As Vault.sol is designed to support more than one underlying token, and given that [rETH, USDC, USDT] are in scope, there is a possibility of adding new tokens as underlying tokens alongside wstETH. It is logical to assume that if support for multiple underlying tokens exists, the current oracle system should accommodate this. However, it does not. As pointed out in the issue, there is no way to configure the current oracle system to support multiple underlying tokens, where one of them is wstETH. Therefore, the only way for the system to function correctly is to have only wstETH as an underlying token. I see this issue as a medium risk because any action taken by the admin to introduce a new token into a Vault with wstETH will lead to incorrect behavior. In the live contracts, the More or less, what this issue indicates is that, even though Vault.sol looks like it supports multiple underlying tokens, in fact, this part of the system is broken in many places, one of which is the oracle system. |
Escalate. Escalating this issue on behalf of the submitter. Please review the above comments. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
If I understand correctly, this means that for this issue to be valid, #197 (comment) must be validated too ? As #266 rely on the fact that 1 stETH != 1 ETH |
Do I understand correctly that you have this assumption based on the code, is it somewhere in the docs? |
Let me rephrase it:
That was the initial meaning, I can see now it could be misinterpreted. |
this is the comment by the sponsor in discord about oracles problems |
I assume you are referring to this, as you linked to the incorrect message: To showcase why this is Medium, I will refer to the following:
And to the currently live code that Mellow currently has multiple live Vaults with a combined TVL of around $550M+. They are using wstETH as the underlying asset. Any action on |
quoting this from the submission,
where is the corruption coming from when adding another underlying? sorry but i think there is something missing |
The current ChainlinkOracle.sol always forces you to determine the base token, and the priceX96() will be based on its price. This requirement forces you to always use cross price querying Z/Y -> Y/X. Preconditions:
Let's consider we want X to be WETH and query the price in USD. We set X to use the ETH/USD price feed. At this point, if any of the Y or Z tokens don't have Y/X or Z/X price feeds, we can't use them in combination. This appears to be a misconfiguration by the admin, since the admin is trusted, it should not be an issue. Now, let's look at a real scenario with rETH and wstETH, where we want to price them in ETH:
Such a setup can be correct, but it needs to block any future interaction with addToken(). Since it does not block interaction with addToken(), any interaction will break the system. As this corner case is possible and any interaction by the admin with the trusted function leads to breaking the system, I see this as a Medium issue. |
okey, thx so much for clarification, i think this should be my last comment but isn't this statement |
As I mentioned in another comment on a different issue, we are now trying to find all possible edge cases where the system works, and I can confirm it will work with a single underlying token. However, the issue is not about a single underlying token but the possibility of adding a new token and how the system reacts to it. |
I agree with the escalation, indeed the protocol wants to integrate 2 underlying tokens in their system, while this report shows how it would break the system. Planning to accept the escalation and leave the issue as it is. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
@z3s @0xklapouchy are there any duplicates? |
This is not appropriate for this discussion and you have already commented this on it. Please refrain from such comments because they do not help in any case. |
You are wrong here, in current live code and in code in audit, adding any of (rETH, USDC, USDT) to the system that have
You missed the In current live code the |
No examples and no facts, you just say you can't add new tokens and that the base token is stETH, which is wrong and you can't prove it. As I said I am open to discussion, but if you give facts where and how it is written that stETH is a base token, until then everything written in the issue is wrong. |
@Slavchew I think you did not read my explanations. Here are the tx from live code for the Steakhouse vault: WETH - set as base token. Oracle configured as described. No use of real Chainlink price feed. aggregatorV3 for WETH used: 0x6A8d8033de46c68956CCeBA28Ba1766437FF840F (ConstantAggregatorV3) Please reread the #266 (comment) The case 1 and case 2 are the possible approaches how admin can start configuring the oracle system, and why he is unable to do it. Case 3 is real configuration of the Mellow Steakhouse vault, and it is showing why addToken() will brake the system. |
Indeed you also confirm that the baseToken is WETH, wstETH is the underlying and of course WStethRatiosAggregatorV3 is used. By this comment, you agree that the baseToken is WETH and only showing the aggregators linked to different tokens which is known to me.The base token is WETH, wstETH is underlying using WStethRatiosAggregatorV3()
That being said, I'm stopping responding to your comments as none of them provide facts and an example of where and when baseToken will be stETH as you stated - @WangSecurity I hope this #266 (comment) of mine is the last to provide facts, that accepting a different |
I agree with @Slavchew arguments. Indeed, WETH is used as a base token, we don't have any information in the README and code comments that there will be other base tokens, only the script linked in the README which shows WETH is used as the base token every time. Based on @Slavchew comments I don't think there will be any problems with adding more underlying tokens and the admin can set custom oracles in Hence, I'm planning to revert the decision and invalidate this issue. @0xklapouchy if still disagree and believe there will be an issue, I'll need you to show a coded POC or an extremely detailed written POC with exact functions and values that would cause an issue. I'll revert the decision on Sunday morning (CEST timezone). |
As mentioned in the issue description, a potential scenario in the Mellow protocol involves a Vault with multiple underlying tokens. Let's consider a Vault with The issue arises in an edge case where There is no mechanism to prevent the Admin from using the
Example ScenarioNow, let's consider a live Vault,
Following the deployment script steps:
Based on the Mellow.finance page, the Vault currently has 51,528 wstETH, used to calculate the current TVL. As of 26.07.2024, 51,528 wstETH ≈ 60,487.1086820949 stETH ≈ 60,440.6545826271 ETH. vault.deposit(user, [50000000000000000000, 50000000000000000000], minLpAmount, deadline); // user address, minLpAmount, and deadline are not important Calculation in the Deposit FunctionCurrent Oracle System:
Total Value:
Deposit Value:
Current Total Supply:
LP Amount:
Correct Oracle System:
Total Value:
Deposit Value:
LP Amount:
Difference in LP AmountsThe difference in LP amounts is:
|
@0xklapouchy I see what the problem is now, since the protocol assumes 1 stETH == 1 ETH, then it just gets the value of wstETH in stETH and counts it as a value in WETH. Hence, the deposit amounts are calculated incorrectly, since the current stETH price is 1.000580 ETH. Is it correct (I know it may sound silly to confirm it but to make sure I understand your argument)? |
@WangSecurity I just want to add why this is not the same issue as other with '1 stETH == 1 WETH', it explain the root problem. The problem here is that current oracle system always force you to use to use cross-price fetch. It would be perfectly fine if it will allow to use Chainlink price feed directly, then you will be able to configure wstETH -> stETH -> WETH as cross, plus rETH / ETH directly. But as it is not allowing that, the base token needs to be the same. And as such it lead to a problem that 1 stETH == WETH if first underlying is wstETH. |
About the other 1 stETH == 1 WETH issue, is it about #299? @0xklapouchy |
Thank you, but in that sense, I believe these are duplicates. The root cause of assuming 1 stETH == 1 WETH gives two vulnerability paths. The first is in case of an increased difference between the prices of 2 assets, leading to an incorrect share amount minted and a loss for a user. The second path is in this report where this assumption would break the protocol when the second token is added, cause the exchange rate would be incorrect, thus, the loss for a user. Both can be fixed with the same fix, of using the chainlink stETH/ETH price feed, for example. In that sense, I believe these issues can be duplicated together because the root cause is the same, the fix is the same, and the impact and the vulnerability path are different, which is sufficient to consider them duplicates. |
I agree it is similar to #29 I can even agree it is duplicate of it, but the issue is only valid when you add additional underlying to wstETH. Most of the duplicates of #29 don't even mention a valid path to this edge case issue. Having 1 stETH == 1 WETH is perfectly fine if you only use 1 underlying token, it is even desired to not fetch stETH / ETH price then, and use constant 1e18 instead. @WangSecurity if you plan to confirm that this issue is valid, and #29 is a duplicate or this issue a duplicate of #29, please recheck on all of #29 duplicates to determine if the explanations were sufficient. |
Thank you for pointing out, I'll check out the duplicates and comment on the ones I don't find sufficient. |
Besides the above 5 issues I think 29 can also be considered a duplicate. |
It still had excluded so I wanted to mention it just in case. Sorry if I opened more work. |
Oh, I see, the excluded label doesn't mean it's not duplicated or not rewarded. This label is set if the issue was invalidated initially during the judging contest (or initial phase of judging, when there's no judging contest as for Mellow). |
eeyore
Medium
Corrupted oracle system if more than 2 underlying tokens are used and one of them is WSTETH
Summary
The
priceX96()
function always enforces a cross-oracle price check, even when a direct price feed is provided by Chainlink.Vulnerability Detail
There is no option to use direct price feeds like RETH/ETH or USDC/ETH without an extra step using
ConstantAggregatorV3
or another Chainlink price feed. The cross-oracle price check is required for WSTETH/STETH and then STETH/ETH price check but should not be enforced for every underlying token used in the protocol.The current system works with only one underlying token, WSTETH, but with the introduction of, for example, rETH as a second underlying token, there is no option to correctly configure the current Oracle system for both tokens to be denominated in the same base token.
In such a scenario, if ETH is used as the base token, the price feed for stETH/ETH needs to be used, or
ConstantAggregatorV3
with a constant 10**18, which will lead to price corruption and indicate that 1 stETH = 1 ETH.Impact
There is no possibility to use the current oracle system and its
priceX96()
function correctly if there is more than one underlying token and one of those tokens is WSTETH.Code Snippet
https://github.com/sherlock-audit/2024-06-mellow/blob/main/mellow-lrt/src/oracles/ChainlinkOracle.sol#L89-L98
https://github.com/sherlock-audit/2024-06-mellow/blob/main/mellow-lrt/src/oracles/WStethRatiosAggregatorV3.sol#L16
https://github.com/sherlock-audit/2024-06-mellow/blob/main/mellow-lrt/src/oracles/ConstantAggregatorV3.sol#L20
Tool used
Manual Review
Recommendation
There should be two different options to acquire the price for a token: direct and cross-oracle. The system should be flexible to use them in parallel. A good example is Euler with its Base and Cross adapters.
The text was updated successfully, but these errors were encountered: