Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New opcode: STATICCALL #214

Merged
merged 12 commits into from
Dec 4, 2017
48 changes: 48 additions & 0 deletions EIPS/static_call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Preamble

EIP: 214
Title: New opcode STATICCALL
Author: Vitalik Buterin <vitalik@ethereum.org>, Christian Reitwiessner <chris@ethereum.org>;
Type: Standard Track
Category: Core
Status: Draft
Created: 2017-02-13

## Simple Summary

To increase smart contract security, this proposal adds a new opcode that can be used to call another contract (or itself) while disallowing any modifications to the state during the call (and its subcalls, if present).

## Abstract

This proposal adds a new opcode that can be used to call another contract (or itself) while disallowing any modifications to the state during the call (and its subcalls, if present). Any opcode that attempts to perform such a modification (see below for details) will result in an exception instead of performing the modification.

## Motivation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be filled with something?

Currently, there is no restriction about what a called contract can do, as long as the computation can be performed with the amount of gas provided. This poses certain difficulties about smart contract engineers: After a regular call, unless you know the called contract, you cannot make any assumptions about the state of the contracts. Furthermore, because you cannot know the order of transactions before they are confirmed by miners, not even an outside observer can be sure about that in all cases.

This EIP adds a way to call other contracts and restrict what they can do in the simplest way. It can be safely assumed that the state of all contracts is the same before and after a static call.

## Specification

Introduce a new `STATIC` flag to the virtual machine. This flag is set to `false` initially. Its value is always copied to sub-calls with an exception for the new opcode below.

Opcode: `0xfa`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not 0xf5, just after the DELEGATECALL?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chriseth @vbuterin same question, any reason to skip 5 opcodes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just took that from some draft, I'm fine with any other value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will be better off choosing random opcodes. If we try to avoid gaps, we need to sort EIPs in a linear ordering, and more communication is needed. On the other hand, if we allow gaps, no communication is necessary unless there is a collision (or, when one party notices a collision, they can simply change the opcode, so maybe no communicaiton is necessary).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is true, though I do not feel it is a valid concern currently, since only one CALL opcode is being added in Byzantium. (The other opcodes, revert, returndata* are sorted out).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this now stay at 0xfa? Also, what is the gas cost for this opcode?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


`STATICCALL` functions equivalently to a `CALL`, except it takes 6 arguments not including value, and calls the child with the `STATIC` flag set to `true` for the execution of the child. Once this call returns, the flag is reset to its value before the call.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One phrase is missing:

Of the 7 arguments of CALL, the excluded value argument is considered as zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this sentence is really bad ;-)
I was of the impression that it actually has only 6 arguments, and in comparison to CALL, the "value" argument is missing.

Copy link
Contributor Author

@chriseth chriseth Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I.e.: ...except it takes 6 arguments (it does not include value) and calls the child...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right and that value is taken to be zero. Perhaps you just meant that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sentence is necessary to exclude the DELEGATECALL-like behavior where the callvalue is taken to be the callvalue of the parent call.


Any attempts to make state-changing operations inside an execution instance with `STATIC` set to `true` will instead throw an exception. These operations include `CREATE`, `CREATE2`, `LOG1`, `LOG2`, `LOG3`, `LOG4`, `SSTORE`, and `SELFDESTRUCT`. They also include `CALL` with a non-zero value. As an exception, `CALLCODE` is not considered state-changing, even with a non-zero value.
Copy link
Member

@axic axic Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also mention that future state changing instructions are included in this list or do we plan to either:

  • update Final EIPs with a growing list
  • deprecate Final EIPs and replace them with ones having updates
  • expect an implementor to follow up every EIP which may introduce new instructions and determine how those change past EIPs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOG0 is missing from the list of state-changing operations
Also wondering why LOG operations are assumed state-changing? They don't change Trie state.
Wouldn't this restrict opcode usage too much?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, LOG0 is missing.

Logs are recorded permanently on the chain, and dApps watch for logs. When dApps find logs, they assume something has happened. STATICCALL should not cause anything "to happen" except for gas consumption and returned data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason for logs being in this list is because there is another EIP that proposes to store logs in the storage of a certain system contract.


## Rationale

This allows contracts to make calls that are clearly non-state-changing, reassuring developers and reviewers that re-entrancy bugs or other problems cannot possibly arise from that particular call; it is a pure function that returns an output and does nothing else. This may also make purely functional HLLs easier to implement.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess HLL stands for "Haskell-like languages", but maybe not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that it stands for just "high level language".


## Backwards Compatibility

This proposal adds a new opcode but does not modify the behaviour of other opcodes and thus is backwards compatible for old contracts that do not use the new opcode and are not called via the new opcode.

## Test Cases

To be written.

## Implementation