The idea is pretty simple, introduce a DELEGATECALL like functionality that restricts state mutations on EVM level just like a STATICCALL does. The idea seems simple and surprised it doesn’t already exist. So I am wondering if there’s any reason this hasn’t already been done? I am no EL dev, but I think the work should be very similar to all other type of calls and could use a lot of reuse(DELEGATECALL + STATICCALL).

This also opens up a very simple way to allow users to write custom views on a foreign contract if the said contract chooses to expose a function that does arbitrary delegatestaticcalls. Would also allow contracts to only keep the core state mutating + necessary view functions and in turn give more room for more code given the code size limits. Could also serve as a poor man’s opt-in workaround for EXTSLOADs too.

contract SomeContract {
  function extview(address _impl, bytes calldata _data) external view returns (bool _success, bytes memory _ret) {
    (_success, _ret) = _impl.delegatestaticcall(_data);

It’s possible (but a bit of a hack) to do something like this by 1) making a normal delegatecall 2) reverting with its return data, and 3) catching the revert and decoding the result of the original call from the error. Here’s one example of the pattern I know of in the wild.

Would definitely be less expensive with its own opcode!

Yes, thats the way to do it right now for sure. But evm level restrictions on mutations would be nice just the same as staticcall. Technically could implement a static call in a similar fashion too.

Revert method requires you to have a new CALL since you want to revert it. Couldn’t be like a internal call jump to a _delegatestaticcall since it will revert the complete existing call. It’d have to be like address(this).call(...) and require more gas as you said and everyone to implement it in their contracts.

1 Like