1

Imagine you have a function like this:

function compute(uint256 a, uint256 b) external pure returns (uint256) {
  return a % b;
}

Does it revert when b is 0?

  • 1
    I think you are confusing EVM with Solidity. From the Yellow Paper Appendix H "Virtual Machine Specification" it should never revert. For example go-ethereum follows the specification. – Ismael Sep 15 at 0:59
  • @Ismael Thanks, updated the question's body. – Paul Berg Sep 15 at 9:56
4

This is answered in the Solidity documentation.

From https://solidity.readthedocs.io/en/v0.5.11/types.html#modulo:

Modulo with zero causes a failing assert.

1

It depends on (1) how you implement the function and (2) how you call it.

As a pure function

This is how it is defined above. The function will NOT revert, since it doesn't end up executed by all the nodes on the network (state-changing methods end up like that).

As a state-changing function

Yes, mod 0 does end up in a reverted tx. This is why OpenZeppelin implemented the mod method in their SafeMath library.

Take this contract as an example:

pragma solidity 0.5.11;

contract ModByZero {

    event LogSomeState(uint256 a, uint256 b);

    function doIt(uint256 a, uint256 b) public returns (uint256) {
        emit LogSomeState(a, b);
        return a % b;
    }
}

And this failed tx on Rinkeby.


See this thread on the Maths StackExchange to learn more about mod 0.

  • The pure function in my test will not revert but cause "invalid opcode". – Ismael Sep 15 at 1:05
  • 1
    If a pure function is called in a transaction, it can certainly cause the transaction to revert. E.g. if this function were called by a contract as part of a transaction. – user19510 Sep 15 at 2:27
1

It reverts, but with INVALID opcode (similar to assert) rather than REVERT opcode (similar to require).

In order to impose the latter, you can add require(b != 0) prior to return a % b.

If b is a user-input value, then you should add this require statement.

If b is an internally-generated value in your system and you know that it is never supposed to be 0, then you can add assert(b != 0) prior to return a % b, or you can leave it as is (since, as mentioned above, a % b will yield the exact same behavior).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.