Solidity – Can a Callee DOS a Function Call if Caller Ignores Success Value?

contract-developmentSecuritysolidity

Consider the following function:


uint256 mySpecialNumber = 0;
function foo(address callee, uint256 newNumber) public {
  mySpecialNumber = newNumber;

  // make a low level call to the bar() function on the callee
  callee.call{gas: gasleft() - 2000}(
    abi.encodeWithSelector(ISomeOtherContract.bar.selector)
  );
}

Is it possible for the callee to DOS or prevent execution of foo()? Or is foo() always executable no matter what the callee does (if it reverts, runs out of gas, or some other error)?

If it is possible for the callee to prevent execution of foo(), how would that be done?

Best Answer

Is it possible for a callee to DOS a function call if the caller ignores the success value?

Yes, but only if the caller doesn't ignore the returndata.

For example, consider this calling function:

function foo(address callee, uint256 newNumber) public {
  (bool success, bytes memory returndata) = callee.call(
    abi.encodeWithSelector(ISomeOtherContract.bar.selector)
  );
}

Even if we ignore success, solidity still needs to read returndata into memory. If callee returns a lot of bytes, this passage can fail due to out-of-gas, reverting the whole transaction.

In your example, where the caller doesn't retrieve the return value, there's no way for the callee to DOS.

How much gas to pass?

I notice you're making the call with gas: gasleft() - 2000. However removing 2000 or a similar small amount isn't necessary.

Indeed, EIP150 makes it that at max gasleft()*63/64 is provided to a child call. In other words, the caller contract is guaranteed to retain 1/64 of gas even if the callee tries to consume it all.

Related Topic