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

ERC DelegateProxy #897

Merged
merged 6 commits into from Apr 22, 2018

Conversation

Projects
None yet
10 participants
@izqui
Copy link
Contributor

izqui commented Feb 22, 2018

Preamble

EIP: <to be assigned>
Title: ERC Proxy
Author: Manuel Araoz (Zeppelin), Jorge Izquierdo (Aragon)
Type: Standard Track
Category: ERC
Status: Draft
Created: 2018-02-21

Simple Summary

Proxy contracts are being increasingly used as both as an upgradeability mechanism
and a way to save gas when deploying many instances of a particular contract. This
standard proposes a set of interfaces for proxies to signal how they work and what
their main implementation is.

Abstract

Using proxies that delegate their own logic to another contract is becoming an
increasingly popular technique for both smart contract upgradeability and creating
cheap clone contracts.

We don't believe there is value in standardizing any particular implementation
of a DelegateProxy, given its simplicity, but we believe there is a lot of value
in agreeing on an interface all proxies use that allows for a standard way to
operate with proxies.

An example implementation of a DelegateProxy can be found in aragonOS or zeppelinOS.

Standardized interface

interface ERCProxy {
  function proxyType() public pure returns (uint256 proxyTypeId);
  function implementation() public view returns (address codeAddr);
}

Code address (implementation())

The returned code address is the address the proxy would delegate calls to at that
moment in time, for that message.

Proxy Type (proxyType())

Checking the proxy type is the way to check whether a contract is a proxy at all.
When a contract fails to return to this method or it returns 0, it can be assumed
that the contract is not a proxy.

It also allows for communicating a bit more of information about how the proxy
operates. It is a pure function, therefore making it effectively constant as
it cannot return a different value depending on state changes.

  • Forwarding proxy (id = 1): The proxy will always forward to the same code
    address. The following invariant should always be true: once the proxy returns
    a non-zero code address, that code address should never change.

  • Upgradeable proxy (id = 2): The proxy code address can be changed depending
    on some arbitrary logic implemented either at the proxy level or in its forwarded
    logic.

Benefits

  • Source code verification: right now when checking the code of a proxy in explorers
    like Etherscan, it just shows the code in the proxy itself but not the actual
    code of the contract. By standardizing this construct, they will be able to show
    both the actual ABI and code for the contract.

Copyright

Copyright and related rights waived via CC0.

@sohkai

This comment has been minimized.

Copy link

sohkai commented Feb 22, 2018

Wondering if implementation() should also include a bytes calldata parameter in the event the proxy changes which implementation to use based on the input.

Maybe this isn't a good use case for this ERC though, most proxies are 1-1 (rather than 1-many).

@izqui

This comment has been minimized.

Copy link
Contributor Author

izqui commented Feb 23, 2018

That's a good point @sohkai, things like ether-router would need this to work.

I think we could make implementation() required and then implementationFor(bytes calldata) an optional function for proxies in which that is relevant.

@maurelian

This comment has been minimized.

Copy link
Contributor

maurelian commented Feb 23, 2018

This previous ERC is worth looking at for historical context: #121 Proxy Standard. Although, I think there is some need to disambiguate the term Proxy.

This ERC seems to be specifically about "proxies that delegate their own logic to another contract".

Whereas the uPort proxy is moreso a "proxy that forwards transactions and calls from any ethereum account".

Would it make sense to call this a "Contract Proxy" or "Computational Proxy"?

@yondonfu

This comment has been minimized.

Copy link

yondonfu commented Feb 24, 2018

I agree with @maurelian - another example of a contract that is a "proxy", but would not fit the description of this interface is the 0x TokenTransferProxy.

Perhaps the standard interface could be named ERCDelegateProxy to convey to users that a contract implementing this interface is acting specifically as a proxy that delegates business logic to another contract while still using its own storage. Contract implementations of ERCDelegateProxy could be named ForwardingDelegateProxy (for proxies that always delegate to the same contract) and UpgradeableDelegateProxy (for proxies that can swap out the implementation contract that they delegate to).

@nicksavers nicksavers added the ERC label Feb 25, 2018

@izqui

This comment has been minimized.

Copy link
Contributor Author

izqui commented Feb 26, 2018

I agree on the name change to DelegateProxy, that is how we call them internally for our own implementation. Regarding other proxy types like uPort's, I think it would be beneficial for those to have a more descriptive name such as AccountProxy.

@izqui izqui changed the title ERC Proxy ERC DelegateProxy Feb 26, 2018

@jbaylina

This comment has been minimized.

Copy link
Contributor

jbaylina commented Feb 26, 2018

I would consider defining an EIP820 Interface.
Using the EIP820 has the advantage that the proxy does not have to implement the ERCProxy code in the same proxy contract. This will save a lot of gas in proxies that share the same code and type, because the implementation of the interface can be done by a singleton contract shared by all the proxies of the same type.

@veox

This comment has been minimized.

Copy link
Contributor

veox commented Mar 2, 2018

@maurelian:

I think there is some need to disambiguate the term Proxy.

@zigguratt has called the particular kind discussed here a dispatcher.

@zigguratt

This comment has been minimized.

Copy link

zigguratt commented Mar 2, 2018

I agree with @maurelian here (and thanks, @veox). There are a couple of different things that could be called proxies. That's exactly why I referred to my implementation as a dispatcher. At the same time, it has the ability to upgrade the contract that it represents.

The idea of swapping out a contract behind a dispatcher/proxy/delegate is a dangerous one. We discussed this at ConsenSys just a couple of day ago. My take on the subject was this (not including uPort's idea of a proxy):

So in the end a proxy or dispatcher should be almost a shield around the contract that it represents, somehow ensuring that if there are any changes made to its sub-contract the changes are clear and very public. But that doesn't stop anyone from using a very simple proxy that does none of that, and at some point swaps out its sub-contract with something nefarious.

This has been on my mind since I implemented my dispatcher. There's actually no way to stop someone from acting badly with a proxy. There would have to be some sort of EVM support, I suspect.

I would love to be proven wrong, believe me.

@Arachnid

This comment has been minimized.

Copy link
Collaborator

Arachnid commented Mar 27, 2018

This is a courtesy notice to let you know that the format for EIPs has been modified slightly. If you want your draft merged, you will need to make some small changes to how your EIP is formatted:

  • Frontmatter is now contained between lines with only a triple dash ('---')
  • Headers in the frontmatter are now lowercase.

If your PR is editing an existing EIP rather than creating a new one, this has already been done for you, and you need only rebase your PR.

In addition, a continuous build has been setup, which will check your PR against the rules for EIP formatting automatically once you update your PR. This build ensures all required headers are present, as well as performing a number of other checks.

Please rebase your PR against the latest master, and edit your PR to use the above format for frontmatter. For convenience, here's a sample header you can copy and adapt:

---
eip: <num>
title: <title>
author: <author>
type: [Standards Track|Informational|Meta]
category: [Core|Networking|Interface|ERC] (for type: Standards Track only)
status: Draft
created: <date>
---
@izqui

This comment has been minimized.

Copy link
Contributor Author

izqui commented Apr 15, 2018

Your comment got somewhat lost and I just saw it. Thanks for the heads-up @Arachnid, it should be good now.

@izqui izqui referenced this pull request Apr 22, 2018

Closed

Update for ERC897 proxies #103

@izqui

This comment has been minimized.

Copy link
Contributor Author

izqui commented Apr 22, 2018

Is anything more required from us before it can be merged @Arachnid?

@Arachnid Arachnid merged commit cf2d761 into ethereum:master Apr 22, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

Arachnid added a commit to Arachnid/EIPs that referenced this pull request May 2, 2018

ERC DelegateProxy (ethereum#897)
* Add ERCProxy draft

* Add missing links

* Re-format EIP897

* ERC897: add reference to implementations
@xinbenlv

This comment has been minimized.

Copy link
Contributor

xinbenlv commented Jul 31, 2018

Hi Jorge(@izqui ), the new rule is pull request can't be the "discussions-to" destination, could you mind update EIP-897 to find an official home for its discussion, given it's still in draft status?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.