sherlock-audit / 2023-06-Index-judging

6 stars 2 forks source link

0x52 - Set tokens with target raises enabled can suffer loss due to sophisticated donation attacks #44

Closed sherlock-admin2 closed 1 year ago

sherlock-admin2 commented 1 year ago

0x52

medium

Set tokens with target raises enabled can suffer loss due to sophisticated donation attacks

Summary

Set tokens that enable target raises can be attacked with sophisticated donation and bidding tactics. The goal is to leave tiny bids open until late in the dutch auction to execute target raises and purchase assets well below market value.

Vulnerability Detail

AuctionRebalanceModuleV1.sol#L1223-L1227

function _canRaiseAssetTargets(ISetToken _setToken) internal view returns (bool) {
    RebalanceInfo storage rebalance = rebalanceInfo[_setToken];
    bool isQuoteAssetExcess = _getDefaultPositionRealUnit(_setToken, rebalance.quoteAsset) > _getNormalizedTargetUnit(_setToken, rebalance.quoteAsset);
    return _allTargetsMet(_setToken) && isQuoteAssetExcess;
}

In order to raise asset targets there must be two conditions. 1) There must be excess quote and 2) all other assets must be at their target weights.

AuctionRebalanceModuleV1.sol#L1084-L1091

    if (_component == address(rebalanceInfo[_setToken].quoteAsset)) return false;

    uint256 normalizedTargetUnit = _getNormalizedTargetUnit(_setToken, IERC20(_component));
    uint256 currentUnit = _getDefaultPositionRealUnit(_setToken, IERC20(_component));

    return (normalizedTargetUnit > 0)
        ? !normalizedTargetUnit.approximatelyEquals(currentUnit, 1)
        : normalizedTargetUnit != currentUnit;

These checks are done to the nearest 1 wei. For 99.9% of all tokens, a variation of 2 wei is a microscopic value. This means that even with negligible variation these checks can be manipulated. Consider the following example:

A set token with 1% target raises enabled has the current allocation:

200,000,000,000 USDC
100,000,000,000,000,000,000 WETH

The manager wants to move the following allocation using USDC as the quote token starting at 150% of market price and linearly decreasing to 50%:

100,000,000,000 USDC
150,000,000,000,000,000,000 WETH

An attacker can manipulate this rebalance to trigger a target raise at an unexpected time. They buy just the right amounts (potentially donating small amounts before bidding) and push the set token to the following state:

100,000,000,005 USDC
149,999,999,999,999,999,000 WETH

Here the set token is technically out of balance but no rational actor will bid because the gas costs would far outweigh the gain. Now the attacker waits for time to pass and the auction price to drop. Right before the end of the auction the attacker donates a small amount of both WETH and USDC then bids a very small amount. This bid updates the unit values for both USDC and WETH. After donation the balances are:

100,001,000,005 USDC
149,999,999,999,999,999,000 WETH

Balances after bid:

100,000,999,900 USDC
150,000,000,000,000,000,000 WETH

With the internal values updated by the the tiny bid, the new balances now qualify the set token for a target raise since WETH is at target and there is still excess USDC. The attacker then calls the function to increase target which sets the new higher target for WETH. The issue now is that the dutch auction is now at 50% of market value. This allows the attacker to buy the WETH at half of market price.

Impact

Set token can be tricked into selling tokens much cheaper than they should be

Code Snippet

AuctionRebalanceModuleV1.sol#L772-L836

Tool used

Manual Review

Recommendation

The reason this attack works is because the attacker is able to create a scenario in which no market participant will finish the rebalance because gas costs would be too high. This is why I would recommend requiring a minimum quote value for each purchase/sale (i.e. $250). This way it would be impossible for the attacker to create this scenario.

pblivin0x commented 1 year ago

Donations should not change the tracked positionUnit for components on SetToken's, so they should not be able to effect an auction.

Oot2k commented 1 year ago

Not a duplicate of 41 and invalid by sponsor comment.