sherlock-audit / 2024-04-arcadia-pricing-module-judging

4 stars 4 forks source link

0x73696d616f - `SlipstreamAM::_getFeeAmounts()` fetches the liquidity of the position, allowing the owner to increase `USD` balance as it pleases #31

Closed sherlock-admin3 closed 6 months ago

sherlock-admin3 commented 6 months ago

0x73696d616f

medium

SlipstreamAM::_getFeeAmounts() fetches the liquidity of the position, allowing the owner to increase USD balance as it pleases

Summary

SlipstreamAM::_getFeeAmounts() fetches the liquidity of position, instead of using the cached liquidity. Thus, users that have pending fees may increase the liquidity of their positions to instantly boost the USD value of their position, as it is pro-rata to liquidity.

Vulnerability Detail

SlipstreamAM::_getFeeAmounts() gets the fees of a position using the actual liquidity of the position in the pool. This is not the case for other asset moduels such as WrappedAerodromeAM, which uses the cached totalWrapped. Due to the fact that fees are calculated pro-rata to liquidity, this means that anyone may increase the USD value of an already deposited assetId, which can serve several different purposes within the protocol and may be used to game it.

Impact

Incosistent and silent increase of the USD value of an account up to principal0 and principal1 which may be used to game the protocol.

Code Snippet

SlipstreamAM::_getFeeAmounts()` fetching the actual liquidity of a position instead of the cached one.

    ...
    function _getFeeAmounts(uint256 id) internal view returns (uint256 amount0, uint256 amount1) {
        (
            ,
            ,
            address token0,
            address token1,
            int24 tickSpacing,
            int24 tickLower,
            int24 tickUpper,
            uint256 liquidity, // gas: cheaper to use uint256 instead of uint128. //@audit here
            uint256 feeGrowthInside0LastX128,
            uint256 feeGrowthInside1LastX128,
            uint256 tokensOwed0, // gas: cheaper to use uint256 instead of uint128.
            uint256 tokensOwed1 // gas: cheaper to use uint256 instead of uint128.
        ) = NON_FUNGIBLE_POSITION_MANAGER.positions(id);
    ...

Tool used

Manual Review

Vscode

Recommendation

Use the cached liquidity to prevent abuse from accounts.

function _getFeeAmounts(uint256 id) internal view returns (uint256 amount0, uint256 amount1) {
    (
        ,
        ,
        address token0,
        address token1,
        int24 tickSpacing,
        int24 tickLower,
        int24 tickUpper,
        , // unnecessary
        uint256 feeGrowthInside0LastX128,
        uint256 feeGrowthInside1LastX128,
        uint256 tokensOwed0, // gas: cheaper to use uint256 instead of uint128.
        uint256 tokensOwed1 // gas: cheaper to use uint256 instead of uint128.
    ) = NON_FUNGIBLE_POSITION_MANAGER.positions(id);

    uint256 liquidity = uint128(assetToLiquidity[assetId]); // get liquidity
    ...
}
0x73696d616f commented 6 months ago

18 only works on newly created pools, the user would lose a part of the fees to the 1e3 liquidity and likely costs a very significant amount of gas.

This attack has no cost as in, assuming the user has the liquidity, he wont pay any extra. The liquidity is still accruing fees, not idle. It works on any pool.

The fix of using cached liquidity also requires adjusting tokenOwed, as explained before.

Thomas-Smets commented 6 months ago

And do what? What is the attack here? He still can't exceed 2X

0x73696d616f commented 6 months ago

Increase the usd balance when the exposure cap was reached, so no deposits could be made, but the user wants to increase the balance, so he figures he can add liquidity to the pool and increase the usd balance up to 2x.

Thomas-Smets commented 6 months ago

That is not an attack. No attack is possible since the total amount is capped. Again, the speed at which we reach the max amount does not matter. Since it could even be in one block via #18. There is no danger for the protocol when a user does that and it is not a disadvantage for other users.

So again, what is the attack?

Thomas-Smets commented 6 months ago

Reducing the speed at which the max value can be reached (especially since there are ways to even bypass those reductions such as #18) does not make the protocol more or less risky.

0x73696d616f commented 6 months ago

So again, what is the attack?

Same as #18 but capped.

0x73696d616f commented 6 months ago

Up to you allowing attackers to manipulate variables as they please.

Hash01011122 commented 6 months ago

@0x73696d616f Please refrain to comment if asked here. @Thomas-Smets Thanks for your input.

cvetanovv commented 5 months ago

When reviewing an issue, the escalation should serve as a additional to the main issue.

The main root of the issue is that the protocol should use cached liquidity. With the first comment, the sponsor shows that this is not true.

Then there is an escalation by watson who agrees with the sponsor and escalates exactly the opposite of what is written in the issue, but I have to look mainly at what is written in the issue. The other comments become redundant because the issue is invalid from the beginning.

Also, there is no specific impact or attack vector in the issue and the recommendation is also wrong.

Planning to reject the escalation and leave the issue as it is.

Hash01011122 commented 5 months ago

Agreed with @cvetanovv judgement. This issue is indeed invalid.

Evert0x commented 5 months ago

Result: Invalid Unique

sherlock-admin4 commented 5 months ago

Escalations have been resolved successfully!

Escalation status: