Vault manager withdrawals cannot access the entire junior tranche
Description
In VaultManager, the internal function _sendUSDCToTrader
sends USDC from the vault to the trader, or, in extreme cases (as noted by the comment), when the vault runs out from the tranches to the trader. It is called when the trader is due USDC due to modifying or closing a position.
function _sendUSDCToTrader(address _trader, uint _amount) internal {
// For the extereme case of totalRewards exceeding vault Manager balance
int256 balanceAvailable =
int(storageT.usdc().balanceOf(address(this))) - int(totalRewards);
if (int(_amount) > balanceAvailable) {
// take difference (losses) from vaults
uint256 difference = uint(int(_amount) - int(balanceAvailable));
uint256 juniorUSDC = (getLossMultiplier() * difference *
getReserveRatio(0)) / 100 / 100;
juniorUSDC = (juniorUSDC > difference) ? difference : juniorUSDC;
uint256 seniorUSDC = difference - juniorUSDC;
junior.withdrawAsVaultManager(juniorUSDC);
senior.withdrawAsVaultManager(seniorUSDC);
}
require(storageT.usdc().transfer(_trader, _amount));
emit USDCSentToTrader(_trader, _amount);
}
When losses need to be taken from the vaults, it calculates juniorUSDC
as a proportion of the difference needed. Note that the call to getLossMultiplier()
and getReserveRatio(0)
both return constant percentages, the base multiplier, and the target reserve ratio respectively, so the ternary that follows is always false. Then, seniorUSDC
is the rest of the difference.
However, this logic means that a percentage of the junior tranche is never withdrawn, whereas all of the senior tranche can be withdrawn.
Impact
Large trade-closing transactions can revert due to insufficient funds in the senior tranche, because funds reserved in the junior tranche cannot be accessed due to this effect. Additionally, for larger awards, this makes the junior tranche safer than the senior tranche, violating economic assumptions.
Recommendations
Correctly calculate the proportion of funds taken from junior and senior tranches such that the junior tranche is always more risky than the senior tranche and the current balances of the tranches are considered.
Remediation
This issue has been acknowledged by Avantis Labs, Inc., and fixes were implemented in the following commits: