Yes, if you delegatecall
to a non-payable function after initially calling with a non-zero msg.value
, the transaction will revert.
Use this example contract as a reference:
//SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
error BatchError(bytes result);
contract DelegateCallNonPayable {
uint public y;
// If we send this function calldata for foo(uint x) and some eth (msg.value), will it revert?
function batch(bytes[] calldata calls) external payable {
uint256 count = calls.length;
for (uint256 i = 0; i < count; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success) {
revert BatchError(result);
}
}
}
// Non-payable function to be called
function foo(uint x) public {
y = x;
}
// Payable function to be called
function payableFoo(uint x) public payable {
y = x;
}
// Get input for `batch()`
function bar(bool z) external pure returns(bytes memory) {
if(z) {
return abi.encodeWithSelector(this.foo.selector, 3);
} else {
return abi.encodeWithSelector(this.payableFoo.selector, 7);
}
}
}
- If you call
batch()
with zero as msg.value
, the function will always succeed using either return data from bar()
.
- The transaction will still succeed if you use the call data for
payableFoo()
and use a non-zero msg.value
.
- The transaction will fail if you use the call data for
foo()
and use a non-zero msg.value
.