orbland / contracts

🔮 Orb and related contracts. Auction + Harberger taxed ownership + invocations.
https://orb.land
MIT License
22 stars 5 forks source link

[MEDIUM] Orb can be made impossible to be bought in a grieving attack #18

Closed odyslam closed 1 year ago

odyslam commented 1 year ago

Description

A sophisticated user can perform the next attack after they become holders of the orb and render the orb impossible to be bought by another person, while also keeping the orb's price to a minimum (even zero).

The user would need to set a relatively simple front-running bot that does the following:

Then, the purchase(oldPrice, newPrice) will always revert, as the oldPrice will have changed. By setting the price to something as small as 1*10e-18, the attacker can invalidate the purchase and, simultaneously, have a little economic cost ( in the context of the orb, the gas cost could be high). The attacked can do that and invalidate all purchase attempts while at the same time keeping themselves solvent (as the price is so low). Thus the issuer can never foreclose the orb and take back control.

It's worth noting that since the Orb has an essential element of a social contract, it doesn't mean that the attacked can reap the benefits of the Orb, as the issue can clearly see the attack and simply select to ignore any triggers. The orb is more or less bricked, and thus, the attack is more of a grieving attack.

Finally, a white-hat hacker could attempt to front-run the attacker's bot and, by winning a gas auction, get their purchase() transaction in front of the attacker's and thus unbrick the orb.

Suggestion

Add a cooldown to set the price, for example, once per day:

uint256 cooldown;
function _setPrice(uint256 newPrice_) internal {
    if(block.timestamp > cooldown){ 
        cooldown = block.timestamp + 24 hours;
        if (newPrice_ > MAX_PRICE) {
            revert InvalidNewPrice(newPrice_);
        }

        uint256 oldPrice = _price;
        _price = newPrice_;

        emit NewPrice(oldPrice, newPrice_);
        } else {
        revert SetPriceCooldown;
    }
}
lekevicius commented 1 year ago

As discussed elsewhere, we consider this DoS attack easily breakable by submitting purchase() tx via private mempool, so no changes to be done.