LibTWAPOracle::consult() function should update prices before returning
Summary
LibTWAPOracle::getTwapPrice() function is used to get DollarToken price and the returned value is used in the major functions like mintDollar() and redeemDollar() in the LibUbiquityPool.sol. However, this function returns average prices without updating.
function getTwapPrice() internal view returns (uint256) {
return
LibTWAPOracle.consult(
LibAppStorage.appStorage().dollarTokenAddress
);
}
//---
function consult(address token) internal view returns (uint256 amountOut) {
TWAPOracleStorage memory ts = twapOracleStorage();
if (token == LibAppStorage.appStorage().dollarTokenAddress) {
// price to exchange 1 Ubiquity Dollar to 3CRV based on TWAP
amountOut = ts.price0Average;
} else {
require(token == ts.token1, "TWAPOracle: INVALID_TOKEN");
// price to exchange 1 3CRV to Ubiquity Dollar based on TWAP
amountOut = ts.price1Average;
}
}
The getTwapPrice() function directly calls the consult(), and returns these values. However, the returned average prices in the consult() function is not up to date. It must update the twapOracleStorage first, and then return the average prices.
Impact
The getTwapPrice() function is used in getDollarPriceUsd() function here, which means getDollarPriceUsd() always returns stale prices. The returned value is used in the two most crucial functions: mintDollar and redeemDollar. All of these actions are performed with stale prices.
function consult(address token) internal view returns (uint256 amountOut) {
+ // update the price first.
+ update();
+ // Then return the average prices in the storage.
TWAPOracleStorage memory ts = twapOracleStorage();
if (token == LibAppStorage.appStorage().dollarTokenAddress) {
// price to exchange 1 Ubiquity Dollar to 3CRV based on TWAP
amountOut = ts.price0Average;
} else {
require(token == ts.token1, "TWAPOracle: INVALID_TOKEN");
// price to exchange 1 3CRV to Ubiquity Dollar based on TWAP
amountOut = ts.price1Average;
}
}
osmanozdemir1
high
LibTWAPOracle::consult()
function should update prices before returningSummary
LibTWAPOracle::getTwapPrice()
function is used to getDollarToken
price and the returned value is used in the major functions likemintDollar()
andredeemDollar()
in theLibUbiquityPool.sol
. However, this function returns average prices without updating.Vulnerability Detail
Down below, you can see the getTwapPrice(), and the consult() functions.
The
getTwapPrice()
function directly calls theconsult()
, and returns these values. However, the returned average prices in theconsult()
function is not up to date. It must update thetwapOracleStorage
first, and then return the average prices.Impact
The
getTwapPrice()
function is used ingetDollarPriceUsd()
function here, which meansgetDollarPriceUsd()
always returns stale prices. The returned value is used in the two most crucial functions:mintDollar
andredeemDollar
. All of these actions are performed with stale prices.Code Snippet
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibTWAPOracle.sol#L111C1-L122C6
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibTWAPOracle.sol#L159C1-L164C6
Tool used
Manual Review
Recommendation
Duplicate of #34