EIP-214 The static call instruction STATICCALL (New opcode STATICCALL)
Final · EVM & execution · EIP status Final · created 2017-02-13
Adds a new instruction, STATICCALL (0xfa), which calls another contract while disallowing any state changes within that call. Any attempt to change state is treated as an exception.
Why it is needed
Currently, once a contract calls another contract, there is no way to prevent the callee from doing whatever it wants as long as there is enough gas. So after making an ordinary call, unless you know exactly what code the called contract runs, you cannot assume anything about the state afterward. Since transaction order is also unknown until a miner finalizes it, even an outside observer cannot be certain of the state in every case. This proposal opens up the simplest way to restrict what the counterparty can do during a call: it becomes safe to assume that every account's state is the same before and after a static call.
What changes
Today
- The called contract can do anything it likes within the gas limit
- After an ordinary call, you cannot assume how state has changed
- Even a call intended only to read data carries the risk of side effects such as reentrancy
After EIP-214
- Calling with STATICCALL forbids all state changes within it (and in any sub-calls)
- An instruction that attempts to change state raises an exception instead of executing
- It becomes safe to assume that all account states are identical before and after a static call
Who is affected
- Smart contract developers: A call that is guaranteed to be read-only can be used, giving confidence that no reentrancy bug can arise from that particular call.
- Code auditors / reviewers: A call made via STATICCALL can be treated as a pure function that only returns output and changes nothing, reducing the scope that needs to be reviewed.
- Client teams: The virtual machine needs to implement the STATIC flag, the new opcode 0xfa, and exception handling for forbidden operations.
- High-level language designers: The original text states that this can make implementing purely functional high-level languages (HLLs) easier.
In depth
Introduction of the STATIC flag
A new STATIC flag is introduced into the virtual machine. Its initial value is false, and that value is always copied down to sub-calls. The sole exception is the new opcode STATICCALL, which sets the flag to true for the child execution. When the call returns, the flag is reset to its value before the call. Because of this flag-propagation rule, the ban on state changes holds for sub-calls of every depth inside a static call.
Opcode format: 0xfa, 6 arguments
The opcode for STATICCALL is 0xfa. Its behavior is equivalent to CALL, but it takes only 6 arguments. CALL's "value" argument is dropped and treated as 0. In other words, a static call cannot send ether. Calling oneself is also possible.
List of forbidden state-changing operations
Attempting a state-changing operation inside an execution instance where STATIC is true raises an exception instead of being performed. These operations are CREATE, CREATE2, LOG0, LOG1, LOG2, LOG3, LOG4, SSTORE, SELFDESTRUCT, and a CALL with nonzero value. As an exception, CALLCODE is not treated as a state change even with nonzero value.
Design intent: guaranteeing pure functions
This proposal lets a contract make a call that is clearly guaranteed not to change state at all. Since that call only returns output and does nothing else, it is a pure function, giving developers and reviewers confidence that no reentrancy bug or other issue can arise from that particular call. The original text adds that this also makes it easier to implement purely functional high-level languages.
Backward compatibility and current status
This only adds a new opcode and does not change the behavior of any other opcode. It is therefore backward compatible with existing contracts that neither use the new opcode nor are called through it. This EIP was proposed on February 13, 2017 by Vitalik Buterin and Christian Reitwiessner, and its status is Final, meaning the spec is already settled.