require v.s. assert in Solidity

There are two usual ways to handle error in Solidity: require and assert.

To summarise, the biggest difference between require and assert is that what developes expect that condition should be.

If developes expect a condition to be normal errors and be safe to be handled, require comes in.

If they do not expect that condition to be false, meaning it should never happen (in a bug-free world), assert is necessary.

key | require | assert ---|---|--- return | Error(string) | Panic(uint256) expectation | expected errors that can be handled | unexpected errors that shold not be present is it a bug? | maybe not, handle it well ✅ | yes, should fix it 👊

Divide by zero?

Then, which would be raised, Error(string) or Panic(uint256), when developers divide by zero?

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0 <0.9.0;

contract C {
    function test() public pure {
        uint num = 5 / 0;
    }
}

This is apparently a bug, and there does not make sense at all to divide numbers with zero (under most of our mathmetical theory). Therefore, in this case Panic(uint256) will be raised.

Pop from an empty array?

I'll give you an another example. What happens if you pop an item from an empty array?

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0 <0.9.0;

contract C {
    uint[] public items;

    function test() public {
        items.pop();
    }
}

Again, this is apparently a bug and it'll raise Panic(uint256).

Summary

There is a lot more topics to consider to decide between require and assert.

But long story short, use require for normal errors that should be handled, and assert if that condidion should never happen in production.

2022-10-30