hats-finance / Wise-Lending-0xa2ca45d6e249641e595d50d1d9c69c9e3cd22573

0 stars 1 forks source link

A missing allowance check in WiseLending:coreLiquidationIsolationPools allows users to liquidate positions with other user's tokens by passing the other user as a _caller #46

Open hats-bug-reporter[bot] opened 6 months ago

hats-bug-reporter[bot] commented 6 months ago

Github username: @c-plus-plus-equals-c-plus-one Twitter username: -- Submission hash (on-chain): 0xb8e886e2470f33a91d8cf07ec15d613dd653619018efc33abaab2d1aec803f4f Severity: high

Description: Description\

A missing allowance check in WiseLending:coreLiquidationIsolationPools allows users to liquidate positions with other user's tokens by passing the other user as a _caller

/**
     * @dev Wrapper function for liqudaiton flow
     */
    function coreLiquidationIsolationPools(
        uint256 _nftId,
        uint256 _nftIdLiquidator,
        address _caller,
        address _paybackToken,
        address _receiveToken,
        uint256 _paybackAmount,
        uint256 _shareAmountToPay
    )
        external
        syncPool(_paybackToken)
        syncPool(_receiveToken)
        returns (uint256)
    {
        CoreLiquidationStruct memory data;

        data.nftId = _nftId;
        data.nftIdLiquidator = _nftIdLiquidator;

        data.caller = _caller;

        data.paybackAmount = _paybackAmount;
        data.tokenToPayback = _paybackToken;
        data.tokenToRecieve = _receiveToken;
        data.shareAmountToPay = _shareAmountToPay;

        data.maxFeeETH = WISE_SECURITY.maxFeeFarmETH();
        data.baseRewardLiquidation = WISE_SECURITY.baseRewardLiquidationFarm();

        _validateIsolationPoolLiquidation(
            msg.sender,
            data.nftId,
            data.nftIdLiquidator
        );

        (
            data.lendTokens,
            data.borrowTokens
        ) = _prepareAssociatedTokens(
            data.nftId,
            data.tokenToRecieve,
            data.tokenToPayback
        );

        return _coreLiquidation(
            data
        );
    }

The above function allows passing an arbitrary _caller and charging him for liquidating the specified NFT position.

A malicious user may get various kinds of profit from that attack.

Recommendations

Foon256 commented 6 months ago

The above statement is not true because there is an allowance check inside the function _validateIsolationPoolLiquidation. As you can see in the implementation, only verified isolation pools are allowed to call this function, making it impossible for other user to call this function. The described check is done in the function _onlyIsolationPool.


     * @dev Internal helper function checking if
     * user inputs are safe.
     */
    function _validateIsolationPoolLiquidation(
        address _caller,
        uint256 _nftId,
        uint256 _nftIdLiquidator
    )
        internal
        view
    {
        _onlyIsolationPool(
            _caller
        );

        if (positionLocked[_nftId] == false) {
            revert NotPowerFarm();
        }

        _checkLiquidatorNft(
            _nftId,
            _nftIdLiquidator
        );

        if (POSITION_NFT.ownerOf(_nftId) != _caller) {
            revert InvalidCaller();
        }
    }
vm06007 commented 6 months ago

@c-plus-plus-equals-c-plus-one seems your submission is invalid