FloorDAO / floor-v2

Floor aims to create a fully onchain governance mechanism for sweeping and deploying NFTs to profitable NFT-Fi strategies as well as seeding liquidity for its own NFT-Fi products.
https://floor.xyz
2 stars 0 forks source link

[NCW-02M] Incorrect Support for Floor Price Reduction #87

Closed tomwade closed 1 year ago

tomwade commented 1 year ago

NCW-02M: Incorrect Support for Floor Price Reduction

Type Severity Location
Logical Fault NewCollectionWars.sol:L369

Description:

The NewCollectionWars::updateCollectionFloorPrice function will significantly misbehave when the floorPrice is reduced as it utilizes unchecked code blocks that deal solely with unsigned integers.

Impact:

The unchecked code block of NewCollectionWars::updateCollectionFloorPrice will significantly misbehave if a floorPrice that is less than the original is specified.

Example:

function updateCollectionFloorPrice(address collection, uint floorPrice) external onlyOwner {
    // Prevent an invalid floor price breaking everything
    require(floorPrice != 0, 'Invalid floor price');

    // Ensure that we have a current war running
    require(currentWar.index != 0, 'No war currently running');

    // Ensure that the collection specified is valid
    bytes32 warCollection = keccak256(abi.encode(currentWar.index, collection));
    require(isCollectionInWar(warCollection), 'Invalid collection');

    // Update the floor price of the collection
    uint oldFloorPrice = collectionSpotPrice[warCollection];
    collectionSpotPrice[warCollection] = floorPrice;

    // Alter the vote count based on the percentage change of the floor price
    if (floorPrice == oldFloorPrice) {
        return;
    }

    // If the collection currently has no votes, we don't need to recalculate
    if (collectionNftVotes[warCollection] == 0) {
        return;
    }

    unchecked {
        // Calculate the updated NFT vote power for the collection
        uint percentage = ((floorPrice * 1e18 - oldFloorPrice * 1e18) * 100) / oldFloorPrice;
        uint increase = (collectionNftVotes[warCollection] * percentage) / 100 / 1e18;
        uint newNumber = (collectionNftVotes[warCollection] + increase);

        // Update our collection votes
        collectionVotes[warCollection] = collectionVotes[warCollection] - collectionNftVotes[warCollection] + newNumber;
        collectionNftVotes[warCollection] = newNumber;
    }
}

Recommendation:

We advise the code to introduce proper support for reducing the floorPrice as the unchecked mathematical code blocks will significantly misbehave.