HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

Attacker changing outcome of the position

Summary

Possible turning the result of the market position upside down

Vulnerability Details

In _positionTokenAmount if we provide the max it will basically remove liquidity of userBalanceLong or userBalanceShort

Attacker can manipulate the long or short position winning by calling _removeLiquidity() and then for example if the short was win and long was lose, Attacker can flashloan the long position token in the pool which will turn the market upside down making long to win and short to lose or the reverse thing. Then when market expires it will result in attacker turning sucessfully the price upside down. This all happens in the same block

Also works with

redeemPositionToken()
function _removeLiquidity(
bytes32 _poolId,
uint256 _positionTokenAmount,
address _recipient
) internal returns (uint256) {
// Query pool parameters to obtain the collateral token as well as the
// short and long token addresses.
IDIVA.Pool memory _pool = IDIVA(_diva).getPoolParameters(_poolId);
// Early check that the pool's collateral token is associated with a registered collateral token.
// This ensures an immediate and graceful revert.
if (_wTokenToCollateralToken[_pool.collateralToken] == address(0)) {
revert CollateralTokenNotRegistered();
}
IERC20Metadata _shortTokenContract = IERC20Metadata(_pool.shortToken);
IERC20Metadata _longTokenContract = IERC20Metadata(_pool.longToken);
IERC20Metadata _collateralTokenContract = IERC20Metadata(_pool.collateralToken);
// Use the user's min short/long token balance if `_positionTokenAmount` equals `type(uint256).max`.
// That corresponds to the maximum amount that the user can remove from the pool.
uint256 _userBalanceShort = _shortTokenContract.balanceOf(msg.sender);
uint256 _userBalanceLong = _longTokenContract.balanceOf(msg.sender);
uint256 _positionTokenAmountToRemove = _positionTokenAmount;
if (_positionTokenAmount == type(uint256).max) {
_positionTokenAmountToRemove = _userBalanceShort > _userBalanceLong ? _userBalanceLong : _userBalanceShort;
}
// Transfer short and long tokens from user to this contract. Requires prior user approval on both tokens.
// No need to use `safeTransferFrom` here as short and long tokens in DIVA Protocol are standard ERC20 tokens
// using OpenZeppelin's ERC20 implementation.
_shortTokenContract.transferFrom(msg.sender /** from */, address(this) /** to */, _positionTokenAmountToRemove);
_longTokenContract.transferFrom(msg.sender /** from */, address(this) /** to */, _positionTokenAmountToRemove);
// Remove liquidity on DIVA Protocol to receive wTokens, and calculate the returned wToken amount (net of DIVA fees)
// as DIVA Protocol's removeLiquidity function does not return the amount of collateral token received.
uint256 _wTokenBalanceBeforeRemoveLiquidity = _collateralTokenContract.balanceOf(address(this));
IDIVA(_diva).removeLiquidity(_poolId, _positionTokenAmountToRemove);
uint256 _wTokenAmountReturned = _collateralTokenContract.balanceOf(address(this)) -
_wTokenBalanceBeforeRemoveLiquidity;
// Conscious decision to omit an early zero amount check here as it will either revert inside `removeLiquidity` due to
// zero DIVA fees (if DIVA fee pct != 0) or in the subsequent call to Aave's `withdraw` function inside `_redeemWTokenPrivate`.
// Withdraw collateral token from Aave, burn wTokens owned by this contract and transfer collateral token to `_recipient`.
uint256 _amountReturned = _redeemWTokenPrivate(
_pool.collateralToken, // wToken
_wTokenAmountReturned,
_recipient,
address(this)
);
return _amountReturned;
}

Impact

High, Attacker manipulated the market

High Risk: The vulnerability allows an attacker to manipulate the market and turn positions upside down, which could result in financial losses for other users or alter the intended market behavior.

  • The attacker can manipulate the outcome of long and short positions by exploiting liquidity removal in a way that changes the market dynamics.

Tools Used

Manualy review

Recommendations

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.