Under the hood, user doesn't need to swap USDC to DSU manually when using Perennial as the protocol wrap that USDC to DSU automatically, if user is using the MultiInvoker contract (or maybe their UI interface).
This wraps assumes that the DSU/USDC price would always be 1:1, which isn’t always the case, for example in the latest USDC depeg, the ratio was changed by a slight difference. In fact, current DSU/USDC rate in Uniswap is 1:0.995.
Looking how past events of current Stable Coins are not guaranteed to be stable, its value should be fetched from an oracle instead, or at least don't just rely on single stable coin.
File: MultiInvoker.sol
237: function _wrap(address receiver, UFixed18 amount) internal {
238: // Pull USDC from the `msg.sender`
239: USDC.pull(msg.sender, amount, true);
240:
241: _handleWrap(receiver, amount);
242: }
...
352: function _handleWrap(address receiver, UFixed18 amount) internal {
353: // If the batcher is 0 or doesn't have enough for this wrap, go directly to the reserve
354: if (address(batcher) == address(0) || amount.gt(DSU.balanceOf(address(batcher)))) {
355: reserve.mint(amount);
356: if (receiver != address(this)) DSU.push(receiver, amount);
357: } else {
358: // Wrap the USDC into DSU and return to the receiver
359: batcher.wrap(amount, receiver);
360: }
361: }
Impact
DSU is pegged to USDC rather than USD which can cause instability and loss of peg
Instead of pegging the DSU to USDC 1:1, use an oracle to fetch the latest price for example in Uniswap (TWAP), Or maybe implement Oracle with a baskets of stable coin to support, instead of solely depends on single USDC.
bitsurfer
medium
Perennial only use DSU as collateral which pegged to USDC open for depeg failure
Summary
Perennial only use DSU as collateral which pegged to USDC open for depeg failure
Vulnerability Detail
Perennial utilized DSU as collateral to participate in the protocol. Based on https://docs.perennial.finance/mechanism/dsu, DSU is wrapped version of USDC.
Under the hood, user doesn't need to swap USDC to DSU manually when using Perennial as the protocol wrap that USDC to DSU automatically, if user is using the
MultiInvoker
contract (or maybe their UI interface).This wraps assumes that the DSU/USDC price would always be 1:1, which isn’t always the case, for example in the latest USDC depeg, the ratio was changed by a slight difference. In fact, current DSU/USDC rate in Uniswap is 1:0.995.
Looking how past events of current Stable Coins are not guaranteed to be stable, its value should be fetched from an oracle instead, or at least don't just rely on single stable coin.
Impact
DSU is pegged to USDC rather than USD which can cause instability and loss of peg
Code Snippet
https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/multiinvoker/MultiInvoker.sol#L237-L242
See above
Tool used
Manual Review
Recommendation
Instead of pegging the DSU to USDC 1:1, use an oracle to fetch the latest price for example in Uniswap (TWAP), Or maybe implement Oracle with a baskets of stable coin to support, instead of solely depends on single USDC.