You can try, but my intuition tells me that it will revert, because your non-constant function will be executed with 0 gas.
For example, suppose that your function is:
function myFunc(address x, uint256 y) public returns (uint256);
Then you can use:
bytes4 private constant MY_FUNC_SELECTOR = bytes4(uint256(keccak256("myFunc(address,uint256)") >> (256 - 4 * 8)));
function callMyFunc(address dest, address x, uint256 y) public view returns (uint256) {
uint256[1] memory ret;
bytes memory data = abi.encodeWithSelector(MY_FUNC_SELECTOR, x, y);
assembly {
let success := staticcall(
gas, // gas remaining
dest, // destination contract address
add(data, 32), // input buffer (starts after the first 32 bytes in the `data` array)
mload(data), // input length (loaded from the first 32 bytes in the `data` array)
ret, // output buffer
32 // output length
)
if iszero(success) {
revert(0, 0)
}
}
return ret[0];
}
Note that if myFunc
returns a tuple of 2 items, for example, then you'll need to modify the above:
function callMyFunc(...) public view returns (uint256, uint256) {
uint256[2] memory ret;
...
64 // output length
...
return (ret[0], ret[1]);
}