2

I'm trying to make sure I fully understand the behavior of try/catch, specifically what state gets reverted when we catch an error. I could not be sure of certain behavior from the v0.8.10 docs. If I have code like:

otherContract.firstMethod()
try otherContract.secondMethod{value: 10, gas: 1000}() {}
catch (bytes memory) {
    // some code
}

Let's say that otherContract.firstMethod and otherContract.secondMethod both modify state within otherContract. If we end up in the catch block, am I correct in the following statements:

  1. the state changes in otherContract made by otherContract.firstMethod will not be reverted
  2. the state changes in otherContract made by otherContract.secondMethod will be reverted

From this question it appears that the 10 sent to otherContract will be refunded but any used gas will not be refunded.

Are all of the above correct? Anything incorrect?

2 Answers 2

3

The try/catch in solidity only check for reverts in call to another contracts.

It doesn't revert state changes by itself. It only allows the caller to detect a revert in the callee.

It is easy to test with a contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A {
    uint public a;

    constructor(uint x) {
        a = x;
    }

    function foo(uint y) public {
        a = y;
    }
}

contract B {
    A public a;

    event Result(uint);

    constructor() {
        // a.a initial value is 1
        a = new A(1);
    }

    function bar() public {
        // sets a.a = 123
        a.foo(123);

        // if successful it will set a.a = 1111
        // call will revert due to out of gas
        try a.foo{gas: 1000}(1111) {
            // This will never be execute due to the revert
            emit Result(8989);
        } catch (bytes memory) {
            // We do nothing in case of revert
        }

        // Read a.a
        uint r = a.a();

        // Emit obtained value (it should be 123)
        emit Result(r);
    }
}
1
  • 1
    So if state changes occur in the called function, in this case a.foo{gas: 1000}(1111), if a.foo reverts, the state changes that occur within the call to a.foo revert. I just tried that without the gas limit to make sure that the state changes were hit, and the above is correct. Thanks for the example.
    – dbmikus
    Dec 8, 2021 at 17:02
0

Basically if the catch is entered, any state change before "try" is kept, as well as anything in the catch. If there is a REVERT within the try block, the entire tx REVERTs (the "try" only applies to the external CALL or contract creation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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