Raspy Black Giraffe
Medium
The use of min(totalCollateral, global.assets) in the _socialize function will cause unfair claim reductions for vault users as temporary collateral mismatches penalize legitimate redemptions.
In Vault.sol#L353-L363, the socialization formula prorates user claims based on min(totalCollateral, global.assets) which fails to distinguish between permanent undercollateralization and temporary mismatches (e.g., pending deposits not yet deployed to markets)
function _socialize(Context memory context, UFixed6 claimAssets) private pure returns (UFixed6) {
return context.global.assets.isZero() ?
UFixed6Lib.ZERO :
claimAssets.muldiv(
UFixed6Lib.unsafeFrom(context.totalCollateral).min(context.global.assets), // Problematic line
context.global.assets
);
}
1- Pending Deposits/Redemptions: global.assets includes pending deposits not yet reflected in totalCollateral. 2- Coordinator Action: The coordinator must delay rebalancing, leaving totalCollateral temporarily mismatched with global.assets.
1- Market Volatility: Asset prices fluctuate between deposit initiation and rebalancing. 2- Delayed Settlement: Oracle updates or market settlements lag, preventing totalCollateral from matching global.assets.
1- User A deposits 100 USDC: global.assets increases by 100 USDC (now 1000 USDC). totalCollateral remains at 900 USDC (deposit not yet deployed).
2- User B redeems 100 USDC: _socialize computes claim as 100 * min(900, 1000) / 1000 = 90 USDC.
3- Result: User B receives 90 USDC instead of 100 USDC, despite the vault being solvent.
Loss Magnitude: Users lose funds proportional to the temporary mismatch (e.g., 10% loss in the example above). Trust Erosion: Repeated unfair reductions degrade user confidence in the vault’s fairness.
No response
Modify _socialize to only apply prorating during true undercollateralization :
function _socialize(Context memory context, UFixed6 claimAssets) private pure returns (UFixed6) {
if (context.global.assets.isZero()) return UFixed6Lib.ZERO;
UFixed6 availableCollateral = UFixed6Lib.unsafeFrom(context.totalCollateral);
// Only apply prorating if the vault is undercollateralized
if (availableCollateral >= context.global.assets) return claimAssets; // Fix
return claimAssets.muldiv(availableCollateral, context.global.assets);
}
This ensures users are penalized only when the vault lacks sufficient collateral, not during transient states.