4

Image contract A, that has the following things:

interface IContractB {
    function methodFromContractB(address account) external;
}
contract ContractA is ERC1155, Ownable {
    IContractB contractB;
    constructor(address _contractB) ERC1155("...") {
        contractB = IContractB(_contractB);
    }
    function myMethod(address something) public {
        _burn(something, 0, 1);
        //do stuff in ContractA
        contractB.methodFromContractB(something);
    }
}

In ContractB, we have:

function methodFromContractB(address account) external onlyContractA {      
  //do stuff in ContractB
  // !!!!!  RUNS OUT OF GAS HERE
  //do some more stuff in ContractB
}

Now, let's say a transaction triggers myMethod . If the transaction runs out of gas right after the do stuff in ContractB , I'm sure it will revert and undo all changes made in do stuff in ContractB. But, will it also undo all changes made in ContractA, more concretely: will the burn happening in ContractA be reverted, resulting in a situation where it is as if the burn never happened?

2 Answers 2

6
+25

With the code you provided, yes, if any call runs out of gas, the whole transaction reverts.

But it's possible to only provide an external function call with a static amount of gas, and surround the call with try/catch statement (https://blog.ethereum.org/2020/01/29/solidity-0.6-try-catch/#:~:text=The%20try%2Fcatch%20statement%20allows,calling%20the%20function%20with%20this.%20.). If the external call is inside a try/catch statement, and the call runs out of gas, the original contract can still continue execution. That is, of course, if there is still gas left for the original contract to continue execution. So if you send all the remaining gas to the target contract (as is in your example), a try/catch wouldn't help anything if the target contract uses up all the gas.

For example here you can see a call which gives only some of the gas: https://ethereum.stackexchange.com/a/101300/31933 : addr.call{gas: 1000000, value: 1 ether}(....

0

All the changes (including do stuff in ContractA) will be reverted.
However, you won't get reimbursed for the gas used for computations. Miners will collect that gas whether the transaction is valid or not.

If the total gas exceeds the gas limit, then all changes are reverted, except that the transaction is still valid and the fee can still be collected by the miner.

Generally speaking, you cannot run out of gas in the middle of a function execution as the required amount of gas is pre-estimated before deployment.

If the total amount of gas used by the computational steps spawned by the transaction, including the original message and any sub-messages that may be triggered, is less than or equal to the gas limit, then the transaction is proceeded.

If somehow the total gas exceeds the gas limit, it means your contract is having some problems and you'll have to make some changes within your code.

Please consider including error handling if you didn't.

2
  • 2
    Yes you can run out of gas in the middle of execution. Two main reasons: 1) estimation failed / was not accurate 2) you didn't use the estimate and/or specified your own limit for some reason Commented Apr 2, 2022 at 17:56
  • Thanks @LauriPeltonen for your comment. Yes I am aware of these exceptions that's why I used "Generally" in my reply. It is good that you mentioned them.
    – LAYcodes
    Commented Apr 4, 2022 at 15:02

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.