EIP-1380: Reduced gas cost for call to self


#1

This topic is intended be the discussion for EIP-1380. Any comment or feedback is very much appreciated!


#2

Seems like a common sense win to me. @axic is there truly zero cost associated with resetting the state/memory in a call to self?


#3

Vyper has been using calls to self for memory safety, cost has been pushing them to move away from that approach. I’m glad to see there is interest from other projects in this.


#4

The proposed use case is cited as a contract calling itself to achieve memory safety while reducing gas cost.

If that is the case, I would like to ask to see an example contract implemented using current best practice of JUMP with the same contract implemented using CALL. This will help find practical contract development issues using this new approach. Also it will help quantify the benefit.


#5

Additionally, the unstated assumption in EIP 1380 is that having a contract CALL itself would serve a useful purpose. Currently I cannot think of useful purposes for this feature.

Specifically, there is ABI function call (OUTER) that wants to do something and it relies on another ABI function call (INNER) to help it. In this case, INNER will not be able to authenticate the beneficial message caller. Will the proposer please offer several contracts that are deployed to mainnet to be analyzed? I will be surprised if any meaningful contracts actually on mainnet would be useful if deployed using CALL to self.

If compensating workarounds are required to make CALL to self work then let’s discuss this in our analysis of these specific contracts. It may be that additional SSTORES are required to do any meaningful tasks. If that is the case then I would consider EIP1380 a case of premature optimization.


#6

I am not sure this is something that we can do, vyper uses CALL (except my work that was done for #901) and solidity uses JUMP. The underlying architecture being a layer lower, we cannot say implement two examples showing one above the other unless we alter the compilers… which I can show you once the 901 is completed and passes all tests - still not sure what this would achieve then?

It would be the job of the separate languages to make the switch the CALL not change anything from the perspective of the contract writer. For vyper the msg.sender being different to solidity, is still an issue I would address (but is outside the scope I would say).


#7
If compensating workarounds are required to make CALL to self work then let’s discuss this in our analysis of these specific contracts. It may be that additional SSTORES are required to do any meaningful tasks. If that is the case then I would consider EIP1380 a case of premature optimization.

Just to clarify no SSTORES will ever be required as we can just pass information to the internal/private functions as parameters. The only issue would be the concept of msg.sender.
INNER function call could easily do any form of authentication using a parameter (but to keep the behaviour of solidity the same msg.sender the same as previous versions it could be passed through as a parameter, with minimal gas cost).

As the proposal motivates, there are significant benefits in having a clean VM state every time you enter a new function, especially because the VM already has the mechanics in place to do actual function calls, having to re-implement call logic on the bytecode level of a contract, because of gas costs, adds just another layer of complexity, and therefore just another layer of issues that could occur.
Also there is the issue of filling up the stack with context variables/memory state.

I will hopefully have the vyper branch done soon, and we can then do some more comparisons if that is useful?


#8

In the case of JUMP the compiler has to ensure that the called function will not change memory (e.g. the entire memory before the operation and after it is equivalent, but the during the function it may change…).

Doing this currently is not implemented in Solidity as it requires a more comprehensive static analyzer or as a simple solution it can disallow anything which uses mstore. That in practice however severely restricts the usefulness of such functions.


#9

The EIP may not have been clear enough, but the reduction happens for all CALL* instructions, including DELEGATECALL, etc. where the context remains mostly the same (with the exception of msg.sender).