Solidity Development – How to Prevent Complete Loss of State if a Call Fails Using address.call()

contract-developmentevmsolidity

CODE:

interface MyInterface {
    function functionName(uint256 x, uint256 y, uint256 z) external returns (uint256[] memory k);
}

Then I've the following inside my contract which uses an outside contract addr:

MyInterface(addr).functionName(x,y,z);
MyInterface(addr).functionName(x,y,z);
MyInterface(addr).functionName(x,y,z);

If any of the 3 function calls fails, I want to stop execution there but making sure any state changes caused by the previous function calls have been saved.

Many times I've seen such transactions on etherscan that execute partially. From what I know, solidity doesn't save any changes if there is an error.

In this answer: Does an entire transaction revert when throw occurs?, it has been mentioned that it is possible using lower level code.

Below is a solution I'm considering:

addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));
addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));
addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));

If one of these calls fails, will the previous state changes caused by the prevoius calls still persist?

Best Answer

the state change will persist if you using low level function like call, you will have to explicitly check for the return value of a 'call' , and revert the entire transaction.

(bool success,) = address.call(.....)
if(!success){
 revert("Failed")
}
Related Topic