The TWAP oracle is using a Curve metapool and incorrectly fetches the price using the LP token of the base pool instead of the underlying tokens.
Vulnerability Detail
Curve metapools are a type of pool that pairs a token, uAD in this case, with another Curve pool, here 3CRV. The intention is to take advantage of an existing pool liquidity when deploying a new pool, which means that the tokens in the metapool are the main token (uAD) and the LP token (3CRV).
The implementation of the TWAP oracle is using the get_dy() function, which calculate the output (dy) of a swap, but since this is a metapool this amount will be expressed in terms of the LP token, which is not the price of the underlying tokens in the base pool (remember the LP token has the accumulated fees).
This means that the uAD oracle will return the price in terms of the LP token, which will be significantly lower than the real correct price.
We can clearly check the issue using the deployed version of TWAPOracle (0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1) that contains the same problem. The price of uAD returned by the oracle is 0.9334:
fugazzi
high
TWAP oracle returns incorrect price
Summary
The TWAP oracle is using a Curve metapool and incorrectly fetches the price using the LP token of the base pool instead of the underlying tokens.
Vulnerability Detail
Curve metapools are a type of pool that pairs a token, uAD in this case, with another Curve pool, here 3CRV. The intention is to take advantage of an existing pool liquidity when deploying a new pool, which means that the tokens in the metapool are the main token (uAD) and the LP token (3CRV).
The implementation of the TWAP oracle is using the
get_dy()
function, which calculate the output (dy
) of a swap, but since this is a metapool this amount will be expressed in terms of the LP token, which is not the price of the underlying tokens in the base pool (remember the LP token has the accumulated fees).This means that the uAD oracle will return the price in terms of the LP token, which will be significantly lower than the real correct price.
We can clearly check the issue using the deployed version of TWAPOracle (
0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1
) that contains the same problem. The price of uAD returned by the oracle is 0.9334:However the current price of uAD is 0.9570 (checked using Curve UI at https://curve.fi/#/ethereum/pools/factory-v2-330/swap):
Impact
The oracle price for uAD is incorrect. This will impact the calculations in
getDollarPriceUsd()
which is used inmintDollar()
andredeemDollar()
.Other contracts not in scope are also likely impacted (LibChef, LibCreditNftManager, LibCurveDollarIncentive).
Code Snippet
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/deprecated/TWAPOracle.sol#L57-L59
Tool used
Manual Review
Recommendation
The oracle should use
get_dy_underlying()
which returns the correct price expressed in terms of the underlying tokens of the base pool.Duplicate of #59