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 XXXX - Standard Contract Upgrade Events #1530

Closed
PhABC opened this issue Oct 26, 2018 · 5 comments
Closed

ERC XXXX - Standard Contract Upgrade Events #1530

PhABC opened this issue Oct 26, 2018 · 5 comments

Comments

@PhABC
Copy link
Contributor

PhABC commented Oct 26, 2018


eip: XXXX
title: Standard for Contract Upgrade Events Proposal
authors: ???
status: Draft
type: Standards Track
category: ERC
created: 2018-10-26

Simple Summary

Various third parties rely on events to track the state of contracts, such as token contracts. By listening to events, these parties can update their local database accordingly to suit their needs. For instance, Etherscan keeps track of ERC-20 and ERC-721 token transfer events to properly reflect users balances. However, contract upgrades can break the event traces if the events are now emitted in a new contract. This break in the event trace forces third parties to manually modify their local database and could easily be avoided if every contract upgrade used a standard event indicating where the new events will be.

Abstract

Establishing a standard on event emitted when contracts are upgraded to ensure contiguous event traces. This will enable third parties to efficiently follow event traces without having to manually intervene in case of a contract upgrade.

Motivation

Event traces can be very helpful for third parties to maintain a local database that is more efficient to query from. For instance, this should be the case for token balances, where one should be able to maintain a valid representation of the current balances of any given token contract by simply listening to events and updating the database accordingly. However, contracts that upgrade their logic while keeping the storage identical will lead to having events emitted in the new proxy contracts. If no standard events are emitted, third parties will be unaware that the events of a given contracts are now happening elsewhere and will be unable to adjust accordingly without manual intervention. This proposal aims to standardize the events emitted during contract upgrades to ensure that all other events can be track in a bidirectional matter.

Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

We will refer to the storage contract as the contract that maintains all the storage variable and that can't be migrated. We will refer to logic contract as the contract that has write and read permission to the storage contract.

Every ERC-XXXX compliant contract must implement the ERC721 and ERC165 interfaces

pragma solidity ^0.4.25;

interface ERCXXXX is ERC165 {
  /**
   * @dev Emitted on the Storage Contract when its logic implementation is upgraded. 
   * MUST be triggered when the first logic contract is set (i.e. `Upgraded(0x0, firstImplementation)`  ). 
   * MUST be triggered everytime a storage contract is upgraded 
   * @param oldImplementation Address of the logic implementation being deprecated.
   * @param oldImplementation Address of the new logic implementation.
   */
  event Upgraded(address indexed oldImplementation, address indexed newImplementation);
}

/**  
 * Note: The ERC-165 identifier for this interface is 0xUNKNOWN 
 *          0xUNKNOWN MUST be set to true if ERC-XXXX is implemented.
 */
interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

Rationale

Imposing this event should be sufficient to allow any third party to track the events describing updates to a storage contract in a forward and backward manner.

Properly using ERC-165 is necessary such that third parties can automatically know that storage related events will be in a separate contract, a contract that can change.

Backwards Compatibility

?

Implementation

To potentially include :

  • Logic contract pointing to their respective storage contract?

  • Logic contract signal via ERC-165 that they only a logic contract?

Questions

  • What happen when multiple storage contracts use the same logic contract? How to best distinguish which storage contract is a given event triggered for?

Copyright

Copyright and related rights waived via CC0.

@coinfork
Copy link
Contributor

coinfork commented Oct 26, 2018

I support this ERC. We need to have a standard way to detect migrations and upgrades to new versions of smart contracts. Watching this thread.

@JamesTherien
Copy link

JamesTherien commented Oct 26, 2018

Yes, this ERC is critical for contract migrations and event-based semantics to work. We need something like this to standardize event scraping.

I think you want events for both the retired contract (pointing to the new one) and the new contract (pointing to the retired one).

I am not sure you even need/want ERC165 since you don't have an API to call. As soon as a contract is live/relevant it should have done an emit already.

@mudgen
Copy link
Contributor

mudgen commented Oct 27, 2018

Does it makes sense to have a third argument to the event which is a reason string, giving some information about why the contract was upgraded? Kind of like a commit message.

@AC0DEM0NK3Y
Copy link
Contributor

AC0DEM0NK3Y commented Oct 27, 2018

Adding from an offline conversation:

If you want to do the delegate call to a contract that sends the events, your API contract will have to have a "this is where my events will come from" function that returns the constant address you will always use to emit your events. Then you can upgrade from v1Logic to v2Logic but both of those return eventsAddress.

So, to me seems like the above ERC should have the retire(old,new) event and both old and new contracts should have a function that returns the events address then that can return "this" or a separate/common contract.

/// @notice Return the address from which this API contract emits its events.
/// @return Address of events contract
function eventsAddress() external view returns (address);

This de-couples API from (delegate) events address/contract so third parties can see where they should subscribe for events without knowing specifics about your particular implementation.

Note: this could maybe return an array of addresses, then you could return your entire chain of upgraded event contracts addresses through this and/or use the retire event + function.

@PhABC
Copy link
Contributor Author

PhABC commented Jan 29, 2019

Closing this as I don't think standardizing this is currently relevant considering most upgradable contract relay on delegate call methods.

If anyone is interested in taking this forward, please free to reply and I can re-open it.

@PhABC PhABC closed this as completed Jan 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants