-
Notifications
You must be signed in to change notification settings - Fork 7
ZeroTrust - In Cross Margin mode, the user’s profit calculation is incorrect. #273
Comments
Hey, @nevillehuang The sponsor’s responses: have at least confirmed that this issue is valid. As for issue 272, the discussion is about having 1 WBTC(Using 1000 USDT as an example would be more appropriate) in cross margin mode. Assuming you invest one WETH (1000 USD) with 1x leverage to go long, should this 1000 USD be borrowed from the LpPool, or can a portion of the 1 WBTC’s value (1000 USD) directly participate in the market trading? 272 and 273 are different issues with different focuses. The root causes in the code are also different. |
Escalate A very simple scenario:
They both go long with 1x leverage in the WETH-USDC market. The final profit situation is as follows(has already been confirmed by the sponsor):
In this case, because using 1 leverage, whether it is cross mode or isolated mode, there is no borrowing from the LP. So finally, the user gets 1 WETH (Both cross and isolated). For cross margin mode: 1 WETH(2000usd) - 1000 usdt = 0.5 WETH |
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. |
We separate the consideration of funds into two parts: one is the user's own margin assets, and the other is the user's position profit. Let's first look at the profit part: regardless of whether it is isolated or cross, their profit is (2000USD-1000USD)/2000 = 0.5 WETH. Margin asset part: since we price the margin in USD at the moment the user opens the position, both isolated and cross margin are 1000USD. Relative to the latest WETH price of 2000USD, the margin becomes 0.5 ETH. So for both cross and isolated users, the settledMargin is 0.5WETH + 0.5WETH = 1 WETH. The user actually invests 1 WETH. For the user, if we disregard the fee issue, the recordPnlToken should be 0. The only difference between isolated and cross margin here is: with cross margin, the user uses their own assets as collateral to borrow 1 WETH to go long on ETHUSD. For the system in terms of opening and closing positions, it is the same as isolated margin, meaning the user uses 1 WETH to go long on ETHUSD. |
You said that “The only difference between isolated and cross margin here is: with cross margin, the user uses their own assets as collateral to borrow 1 WETH to go long on ETHUSD.” |
Let's focus on this issue here and keep the discussion about #272 there. As I understand this comment the protocol is working as it should, but i might be missing something, so please correct me. |
The sponsor’s statement that This is why I pointed out in other issues that they need to actually borrow. |
As I understand you again talk about #272 and let's keep the discussion about it under #272. As I understand this report is only a design recommendation and not a real issue. But if I'm missing why this one is a valid issue, please correct me. |
This is definitely a serious issue. User's profit have been lost. I have proven the loss of funds using PoC and test code. A very simple scenario:
However, the Proof of Code shows that in cross margin mode, the profit is 0. The profit being 0 is clearly incorrect. Anyone with trading experience would immediately know that the profit of 0 is wrong. It is very important for the judgment of this issue to note that some statements made by the sponsor are not based on the factual code.
The user actually invests 1 WETH. — This is not true; the cross margin user invests 1000 USDT.
The user uses their own assets as collateral to borrow 1 WETH to go long on ETHUSD. — This is not true, they did not borrow 1 WETH from anyone. The sponsor cannot specify who the lender is, the process of the borrow transaction, or whose account decreased by 1 WETH. I have already provided PoC and test results. However, the sponsor refutes me based on assertions that are not true of the code. Moreover, the proof of concept I provided is very simple and should be understandable to everyone, especially for those with token trading experience—it’s clear at a glance. |
Thank you for such a thorough response, I believe you're correct here and this issue is indeed valid. As I understand it will happen is almost every trade due to incorrect formula, correct? |
Thank you very much, planning to accept the escalation and validate the issue with high severity, cause the constraints are not extreme. |
@0xELFi @0xELFi02 @nevillehuang @WangSecurity |
Result: |
Escalations have been resolved successfully! Escalation status:
|
ZeroTrust
High
In Cross Margin mode, the user’s profit calculation is incorrect.
Summary
In Cross Margin mode, the user’s profit calculation is incorrect.
Vulnerability Detail
We know that isolated and cross margin are different. When a position is created, in isolated mode, the corresponding assets need to be transferred from the user’s wallet to the MarketVault, while in cross margin mode, the user only needs to have sufficient collateral in the PortfolioVault (any supported collateral will do).
For example, with 1x leverage going long on WETH-USDC, the position size is 1 WETH, and the price of WETH is 1000 USD.
In isolated mode, when establishing the position, 1 WETH is transferred to the MarketVault, so the borrowing is 0.
In cross margin mode, assuming the collateral in the PortfolioVault is 10,000 USDC, no funds are transferred when creating the position.
When the price of WETH rises to 2000 USD, closing the position makes it more evident.
In isolated mode: The user profits 1000 USD (2000 USD - 1000 USD initial capital), and finally still gets their original 1 WETH (2000 USD), which is used for trading.
In cross margin mode: The user profits 1000 USD (2000 USD - 1000 USD initial borrowed funds), and finally gets 0.5 WETH.
However, in _updateDecreasePosition, cache.recordPnlToken = cache.settledMargin - cache.decreaseMargin.toInt256(), where cache.decreaseMargin = cache.position.initialMargin, causing cache.recordPnlToken to be nearly zero.
This is incorrect in cross margin mode, because in cross margin mode, the initialMargin (with) is not invested in the market. Therefore, cache.recordPnlToken = cache.settledMargin.
poc
For example, with 1x leverage going long on WETH-USDC, the position size is 1 WETH, and the price of WETH is 1000 USD.
When the price of WETH rises to 2000 USD, closing the position makes it more evident.
Test the base code to verify this.
It can be seen that the profit is a negative value close to zero, which is obviously incorrect.
Impact
This causes financial loss for either the user or the protocol.
Code Snippet
https://github.com/sherlock-audit/2024-05-elfi-protocol/blob/main/elfi-perp-contracts/contracts/process/DecreasePositionProcess.sol#L60
https://github.com/sherlock-audit/2024-05-elfi-protocol/blob/main/elfi-perp-contracts/contracts/process/DecreasePositionProcess.sol#L206
Tool used
Manual Review
Recommendation
Distinguish between the handling methods for isolated mode and cross margin mode.
The text was updated successfully, but these errors were encountered: