Search code examples
ethereum

Assert vs. require within Solidity?


My understanding is that "require" refunds the remaining gas if it fails whereas "assert" doesn't.

I'm a bit confused though b/c what is meant by remaining gas? I often specify a gas limit of a very large number even when the contract I'm calling requires very little.

If I were to specify 4,700,000 gas limit, and only 50,000 gas was required, but "assert" failed in the called contract, would I lose all 4,700,000 gas?


Solution

  • Yes, you would lose the entire amount (or close to it). assert is effectively the catastrophic bail out of the transaction due to something completely unexpected. It should be used to check for things like making sure your contract hasn't wound up in an invalid state, avoid divide by 0, over/underflow, etc.

    require, on the other hand, will only consume the gas used up to the point of failure. The remaining gas will be refunded.

    The gas limit you specify shouldn't be arbitrarily high. When you initiate a transaction, the full amount of gas you specify is sent and whatever is left at the end of execution is refunded back to you. Not only are you exposing yourself to asserts in your own contract, but if you call other contracts from your own, you are giving that contract a lot of bandwidth to do whatever it wants with the gas you pass on to it.

    Example showing gas consumption:

    pragma solidity ^0.4.16;
    
    contract Test {
        function run(uint8 i) public pure {
            uint8 total = 0;
    
            for (uint8 j = 0; j < 10; j++)
              total += j;
    
            assert (i < 20);
            require (i < 10);
    
            for (j = 0; j < 10; j++)
              total += j;
        }
    }
    

    All tests run with gas limit = 5000000

    Test #1 - run(8): Function runs successfully - 1860 gas consumed.

    enter image description here

    Test #2 - run(15): Function passes assert, fails at require. Only first loop is run - 1049 gas consumed.

    enter image description here

    Test #3 - run(25): Function fails at assert. Again, only first loop is run - 4978536 gas consumed (ouch).

    enter image description here