Skip to content

Add ERC: Versioned Proxy Contract Interface #1017

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

Merged
merged 7 commits into from
Jun 16, 2025
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions ERCS/erc-7936.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
eip: 7936
title: Versioned Proxy Contract Interface
description: A standard interface for proxy contracts that allows callers to select implementation versions

Check failure on line 4 in ERCS/erc-7936.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble header `description` should not contain `standard` (or similar words.)

error[preamble-re-description]: preamble header `description` should not contain `standard` (or similar words.) --> ERCS/erc-7936.md:4:13 | 4 | description: A standard interface for proxy contracts that allows callers to select implementation versions | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ prohibited pattern was matched | = info: the pattern in question: `(?i)standar\w*\b` = help: see https://ethereum.github.io/eipw/preamble-re-description/
author: Raphina Liu (@Stamp9), Monica Jin (@mokita-j), Martin Monperrus (@monperrus)
discussions-to: https://ethereum-magicians.org/t/new-erc-versioned-proxy-contract-interface/23743
status: Draft
type: Standards Track
category: ERC
created: 2025-04-17
---

Check failure on line 12 in ERCS/erc-7936.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

body is missing section(s): `Security Considerations`, `Copyright`

error[markdown-req-section]: body is missing section(s): `Security Considerations`, `Copyright` --> ERCS/erc-7936.md | | = help: must be at the second level (`## Heading`) = help: see https://ethereum.github.io/eipw/markdown-req-section/
## Abstract

This EIP standardizes an interface for proxy contracts that allows callers to explicitly select which version of an implementation contract they want to interact with. Unlike traditional proxy patterns that only expose the latest implementation, this standard enables backward compatibility by maintaining access to previous implementations while supporting upgrades. The versioned proxy maintains a registry of implementation addresses mapped to version identifiers, allowing callers to specify their desired version at call time.

## Motivation

Smart contract upgrades are essential for fixing bugs and adding features. Current proxy patterns typically force all callers to use the latest implementation, which can break existing integrations when interfaces change.

Furthermore, traditional proxy patterns expose all users to risk if an upgrade is malicious, as they have no choice but to use the latest implementation. This standard allows users to remain on verified versions they trust, mitigating the risk of a compromised admin key or governance process deploying harmful code.

This EIP addresses several key problems:

1. **Breaking Changes**: Interface changes in new implementations can break existing integrations.
2. **Gradual Adoption**: There is no standard way to allow gradual adoption of new contract versions.
3. **Malicious Upgrades**: Users today must trust proxy admins indefinitely, as they can't opt out of potentially harmful upgrades without ceasing use of the contract entirely.
4. **Trust Assumptions**: Contract users must maintain perpetual trust in governance or admin keys, with no ability to selectively trust specific, audited implementations.

## 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.

### Interface

```solidity

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change

interface IVersionedProxy {
/// @notice Emitted when a new implementation version is registered
/// @param version The version identifier
/// @param implementation The address of the implementation contract
event VersionRegistered(bytes32 version, address implementation);

/// @notice Emitted when the default version is changed
/// @param oldVersion The previous default version
/// @param newVersion The new default version
event DefaultVersionChanged(bytes32 oldVersion, bytes32 newVersion);

/// @notice Registers a new implementation version
/// @param version The version identifier (e.g., "1.0.0")
/// @param implementation The address of the implementation contract
function registerVersion(bytes32 version, address implementation) external;

/// @notice Removes a version from the registry
/// @param version The version identifier to remove
function removeVersion(bytes32 version) external;

/// @notice Sets the default version to use when no version is specified
/// @param version The version identifier to set as default
function setDefaultVersion(bytes32 version) external;

/// @notice Gets the implementation address for a specific version
/// @param version The version identifier
/// @return The implementation address for the specified version
function getImplementation(bytes32 version) external view returns (address);

/// @notice Gets the current default version
/// @return The current default version identifier
function getDefaultVersion() external view returns (bytes32);

/// @notice Gets all registered versions
/// @return An array of all registered version identifiers
function getVersions() external view returns (bytes32[] memory);

/// @notice Executes a call to a specific implementation version
/// @param version The version identifier of the implementation to call
/// @param data The calldata to forward to the implementation
/// @return The return data from the implementation call
function executeAtVersion(bytes32 version, bytes calldata data) external payable returns (bytes memory);
}
```

### Behavior Requirements

1. The proxy contract MUST maintain a mapping of version identifiers to implementation addresses.
2. The proxy contract MUST maintain a default version that is used when no version is specified.
3. When `executeAtVersion` is called, the proxy MUST:
- Verify the specified version exists
- Forward the call to the corresponding implementation
- Return any data returned by the implementation
4. The proxy contract MUST emit appropriate events when versions are registered, or when the default version changes.
5. The proxy contract SHOULD implement access control for administrative functions (registering versions, setting default).
6. The proxy contract MAY implement EIP-1967 storage slots for compatibility with existing tools.

Check failure on line 93 in ERCS/erc-7936.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7936.md | 93 | 6. The proxy contract MAY implement EIP-1967 storage slots for compatibility with existing tools. | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+` = help: see https://ethereum.github.io/eipw/markdown-link-first/

### Fallback Function

The proxy contract SHOULD implement a fallback function that forwards calls to the default implementation version when no version is specified. This maintains compatibility with traditional proxy patterns.

## Rationale

### Version Identifiers as bytes32

Version identifiers are specified as `bytes32` rather than semantic versioning strings to:
1. Provide flexibility in versioning schemes
2. Reduce gas costs for storage and comparison
3. Allow for both string-based versions (converted to bytes32) and numeric versions
4. Allow for storing a Git commit identifier in SHA-1 or SHA-256

### Explicit Version Selection

The standard requires callers to explicitly select a version through `executeAtVersion` rather than encoding version information in the call data to:
1. Maintain a clean separation between version selection and function calls
2. Avoid modifying existing function signatures
3. Make version selection explicit and auditable

### Registry Pattern

The registry pattern was chosen over alternatives like:
1. **Multiple Proxies**: Having separate proxies for each version would increase deployment costs and complexity
2. **Version in Storage**: Storing a single "current version" would not allow different callers to use different versions simultaneously

### Default Version

The default version mechanism allows the proxy to maintain compatibility with traditional proxy patterns and supports callers that don't need to specify a version.

## Backwards Compatibility

This EIP is designed to enhance backward compatibility for smart contracts. It does not introduce any backward incompatibilities with existing Ethereum standards or implementations.

Existing contracts that interact with proxy contracts can continue to do so without modification, as the fallback function will route calls to the default implementation.

## Reference Implementation

TBD
Copy link
Contributor

Choose a reason for hiding this comment

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

You'll need to include the copyright waiver from the template.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done @SamWilsn also fixing the other CI checks

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
## Reference Implementation
TBD

Remove this section until you're ready to add it.

Loading