Atomic Wool Tuna
Medium
Attacker will manipulate TWAP-to-USD conversion to overvalue collateral, impacting leveraged positions.
The unvalidated TWAP-to-USD conversion logic in the Leverager will cause an overvaluation of collateral for leveraged positions as a token lacking a price feed is valued solely via the pool’s TWAP.
This allows an attacker to manipulate the TWAP through incremental swaps, overvalue collateral, and open undercollateralized loans that eventually lead to losses for protocol participants.
In the _calculateTokenValues function of the Leverager contract, if a token does not have a Chainlink price feed, its USD value is derived exclusively from the pool’s TWAP price.
/// @notice Calculates the USD value of amount0 and amount1
/// @dev Requires at least one of them to have set a trustworthy pricefeed.
/// If one of them doesn't have a pricefeed, it uses the pool TWAP price to convert said token to the other one.
/// @param token0 The address of the first token
/// @param token1 The address of the second token
/// @param amount0 The amount of token0
/// @param amount1 The amount of token1
/// @param price The TWAP token0/token1 price.
/// @return usdValue The total token value, denominated in USD, scaled in 1e18.
function _calculateTokenValues(address token0, address token1, uint256 amount0, uint256 amount1, uint256 price)
internal
view
returns (uint256 usdValue)
{
uint256 chPrice0;
uint256 chPrice1;
uint256 decimals0 = 10 ** ERC20(token0).decimals();
uint256 decimals1 = 10 ** ERC20(token1).decimals();
if (IPriceFeed(pricefeed).hasPriceFeed(token0)) {
chPrice0 = IPriceFeed(pricefeed).getPrice(token0);
usdValue += amount0 * chPrice0 / decimals0;
}
if (IPriceFeed(pricefeed).hasPriceFeed(token1)) {
chPrice1 = IPriceFeed(pricefeed).getPrice(token1);
usdValue += amount1 * chPrice1 / decimals1;
}
// If chPrice0 is 0, it means token0 doesnt have a pricefeed.
// Therefore, convert it token1 and from there, convert it to USD
if (chPrice0 == 0) {
usdValue += (amount0 * price / PRECISION) * chPrice1 / decimals1;
} else if (chPrice1 == 0) {
usdValue += amount1 * PRECISION / price * chPrice0 / decimals0;
}
return usdValue;
}
The choice to use only the TWAP without additional validation or cross-checking against the spot price is a conceptual mistake, as it enables an attacker to manipulate the conversion rate through incremental swaps.
- The leveraged position must involve a token that lacks a Chainlink price feed, causing its USD value to be determined solely by the pool’s TWAP.
- The TWAP interval and the allowed deviation
maxObservationDeviation
are set such that an attacker can perform incremental swaps to shift the TWAP gradually without triggering safeguards. - The
_calculateTokenValues
function relies solely on the TWAP price for USD conversion without validating or cross-checking with the current spot price.
- The underlying liquidity pool for the token in question must have relatively low liquidity, enabling small trades to significantly affect the TWAP.
- Attacker executes small swaps in the low-liquidity pool over the TWAP interval, inflating the price of the token by staying within
maxObservationDeviation
. - Attacker opens a leveraged position using the manipulated token as collateral, borrowing excess funds against the inflated value.
- Post-manipulation price correction triggers liquidation, but collateral recovery is insufficient to cover the debt.
The protocol suffers bad debt equal to the difference between the borrowed amount and recovered collateral.
Step 1: Identify TokenA used as collateral that lacks a dedicated price feed. Step 2: Perform incremental swaps to shift the TWAP upward. Step 3: With the TWAP now manipulated, prepare leveraged position parameters. Step 4: Open a leveraged position using the inflated collateral value. Step 5: Post-manipulation, a market correction will lead to liquidation, resulting in losses for the protocol.
- Require that tokens used for collateral via TWAP conversion meet a minimum liquidity threshold to reduce the feasibility of manipulation through small incremental swaps.
- Enforce additional checks on the TWAP price by cross-verifying it against the current spot price or using an alternative trusted price feed for USD conversion.
- Furthermore, shorten the TWAP interval or tighten the allowed deviation of
maxObservationDeviation
to minimize the manipulation window and limit the impact of incremental swaps.