Platform: Code4rena
Start Date: 09/01/2024
Pot Size: $100,000 USDC
Total HM: 13
Participants: 28
Period: 28 days
Judge: 0xsomeone
Total Solo HM: 8
Id: 319
League: ETH
Rank: 11/28
Findings: 1
Award: $2,116.86
🌟 Selected for report: 0
🚀 Solo Findings: 0
2116.8629 USDC - $2,116.86
https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L1205-L1211 https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L1046
Shrine has a recovery
mode feature, which is activated when the aggregated loan-to-value ratio of all troves in the Shrine is equal to or greater than 70% of the Shrine's threshold
Recovery mode adjusted downwards depending on the the extent to which the Shrine's aggregate loan-to-value ratio is greater than the Shrine's recovery mode threshold, down to a floor of 50% of the yang's original threshold. We can see that recoveryMode
is considered active dynamically, when a health for a trove is checked, which means that there is a function, which is calculation the weighted average of the thresholds of all yangs, which are supported by the system, amount of all depts and value of all deposited yangs (LTV). And it check whether (value of all dept / value of all yangs) > 70%
, and if it is true, threshold for give trove is being scaled by the corresponding value.
if self.is_recovery_mode_helper(shrine_health) { let recovery_mode_threshold: Ray = shrine_health.threshold * RECOVERY_MODE_THRESHOLD_MULTIPLIER.into(); return max( threshold * THRESHOLD_DECREASE_FACTOR.into() * (recovery_mode_threshold / shrine_health.ltv), (threshold.val / 2_u128).into() ); }
As the system is cross-margin and we expect different yangs with different thresholds, this means that average threshold depends on deposited amount of each yang and the corresponding dept minted agains it (it LTV value). This means that if we have yangs for stablecoins, which threshold would be larger (~90%), this could significantly change the average threshold) and so -> LTV.
Here is the formula, which is calculating weighted average of the thresholds:
(yangADeposited / totalDeposited) * yangA% + (yangBDeposited / totalDeposited) * yangBDeposited% = weighted average of the thresholds %
(Note that this is for only two yangs and it can go on for as many collateral assets there are)
and the total LTV is calculated as follows:
allTrovesDept/allDepositedYangsValue
<a href="https://imgur.com/9ETzX5i"><img src="https://i.imgur.com/9ETzX5i.png" title="source: imgur.com" /></a>
Lets take a look at an example values, which are real for production enviroment:
Yang with threshold of 70% and current LTV 65% (minted yin = 3.25M ;deposited collateral = 5M)
Yang with threshold of 60% and current LTV 55% (minted yin = 2.75M; deposited collateral = 5M)
Yang with threshold of 90% (suppose a stablecoin) (18M minted)
(5M / 30M) * 70% + (5M / 30M) * 60% + (20M / 30M) * 90% = 81%
, so the manipulation has raised the threshold from avg of 65% -> 81% (16%)(2.75M + 3,25M + 18M) / 30M = 80%
(10% > recovery mode threshold)Manual Review
Context
#0 - tserg
2024-02-07T09:58:38Z
This is valid - duplicate of #205.
#1 - c4-pre-sort
2024-02-10T09:01:04Z
bytes032 marked the issue as sufficient quality report
#2 - c4-pre-sort
2024-02-10T09:01:17Z
bytes032 marked the issue as duplicate of #205
#3 - c4-judge
2024-02-26T16:45:39Z
alex-ppg marked the issue as satisfactory