Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
43 changes: 43 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: |
forge --version

- name: Run Forge fmt
run: |
forge fmt --check
id: fmt

- name: Run Forge build
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
id: test
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Compiler files
cache/
out/

*.org
.env
.DS_Store
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["prettier-plugin-solidity"]
}
96 changes: 95 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,95 @@
# semver-proxy
# SemVer Proxy
Proxy contract that allows dispatching calls to multiple implementations, based on [Semantic Versioning](https://semver.org/). Automatically handles incrementation of `major.minor.patch` parts of a version during upgrades, but it *doesn't enforce proper adherence to Semantic Versioning by developers on a smart-contract level* - it's considered to be a responsibility of a smart-contract developer to properly adhere to Semantic Versioning.

## Quick Start
```sh
git clone https://github.com/daoio/semver-proxy

## Install deps (note, oz contracts are already installed locally with --no-git)
forge install
## Run tests
forge test
```

## Storage layout of `SemVerProxy`
`SemVerProxy` reserves storage slots **0 to 99** for implementation contracts by declaring a fixed-size array that occupies these slots:
```solidity
uint256[100] private __gap; // Reserves slots 0-99 for implementations
```
So, the storage layout of a proxy and an arbitrary implementation contract can be represented as follows:
```text
Proxy storage layout:
┌─────────────┐
│ Slot 0-99 │ ← `__gap` placeholder (reserved for implementations)
├─────────────┤
│ Slot 100 │ ← `_latestVersion`
│ Slot 101 │ ← Other state variables
│ ... │
└─────────────┘

Implementation storage example:
┌─────────────┐
│ Slot 0 │ ← Implementation's first state variable
│ Slot 1 │ ← Implementation's second state variable
│ ... │
│ Slot 99 │ ← Last available slot for implementation
├─────────────┤
| Slot 100 | ← ⚠️ This will collide with proxy's storage
└─────────────┘
```

## Releases and Versioning
A **release** refers to a versioned implementation contract stored in the proxy. Unlike standard proxies, `SemVerProxy` maintains multiple implementations simultaneously, each accessible through its semantic version.

- **Latest Release**: Stored in the [ERC-1967 implementation slot](https://eips.ethereum.org/EIPS/eip-1967#logic-contract-address)
(Updating this overwrites the ERC-1967 slot)
- **Historical Versions**: Preserved in the `_releases` mapping
(All versions remain accessible to clients by their `major.minor.patch` identifier)
- **Initial Version**: `0.1.0` per [SemVer initial development guidelines](https://semver.org/#how-should-i-deal-with-revisions-in-the-0yz-initial-development-phase)

### Version Upgrade
Admins can release new version of implementation contract via the following function calls (effectively upgrading proxy to use new implemenation, though clients might still use previous versions of the implementation contract):

| Function | Behavior | Example |
| ------------- | ------------- | -- |
| `releasePatch` | Increments patch | `1.2.3` → `1.2.4` |
| `releaseMinor` | Increments minor, resets patch | `1.2.3` → `1.3.0` |
| `releaseMajor` | Increments major, resets minor and patch | `1.2.3` → `2.0.0` |

## Subscribing to Specific Versions
By default, all non-admin calls that end up in `fallback()` function are dispatched to `delegatecall` to the latest release (stored in ERC-1967 slot). But, users can "subscribe" to use the implementation version they need, by calling:
```solidity
function subscribeToVersion(Version memory version) external;

// Where {Version} is:
struct Version {
uint64 major;
uint64 minor;
uint128 patch;
}
```
After this action all calls of a subscribed user will be dispatched to the `major.minor.patch` version they have specified for subscription. All subscriptions are stored inside `SemVerProxy._subscribedClients` mapping
```mermaid
flowchart TD
A(["subscribed to 1.0.1"]) --> n4["SemVerProxy"]
n1(["subscribed to 0.1.0"]) --> n4
n2(["not subscribed"]) --> n4
n4 --> C["Release v 1.0.1"] & D["Release v 0.1.0"] & n3["Latest Release v 2.0.0"]
n4@{ shape: diam}
n3@{ shape: rect}
linkStyle 0 stroke:#D50000,fill:none
linkStyle 1 stroke:#2962FF,fill:none
linkStyle 2 stroke:#00C853,fill:none
linkStyle 3 stroke:#D50000,fill:none
linkStyle 4 stroke:#2962FF,fill:none
linkStyle 5 stroke:#00C853
```

Users can unsubscribe from using specific version and use the latest one by calling:
```solidity
function unsubscribeFromVersioning() external;
```

## Security Considerations
- Since `SemVerProxy` only reserves slots from 0 to 99, any 100+ slot of the implementation will collide with proxy.
- `SemVerProxy` has externally accessable function, therefore there's a possibiliy of function selector clash (i.e., if implementation defines functions that have the same signature as external functions of `SemVerProxy`).
10 changes: 10 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

[invariant]
runs = 1000
depth = 300

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions lib/forge-std
Submodule forge-std added at 77041d
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/all-geese-stand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': patch
---

Add constructors to the different signers.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/clean-ways-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`AccountERC7579`: Extension of `Account` that implements support for ERC-7579 modules of type executor, validator, and fallback handler.
12 changes: 12 additions & 0 deletions lib/openzeppelin-contracts/.changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "OpenZeppelin/openzeppelin-contracts"
}
],
"commit": false,
"access": "public",
"baseBranch": "master"
}
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/eight-radios-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Checkpoints`: Add a new checkpoint variant `Checkpoint256` using `uint256` type for the value and key.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/fine-frogs-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableMap`: Add `keys(uint256,uint256)` that returns a subset (slice) of the keys in the map.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/full-ways-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EIP7702Utils`: Add a library for checking if an address has an EIP-7702 delegation in place.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/funny-years-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Account`: Added a simple ERC-4337 account implementation with minimal logic to process user operations.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/hot-grapes-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableSet`: Add `values(uint256,uint256)` that returns a subset (slice) of the values in the set.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/lazy-poets-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`SignerERC7702`: Implementation of `AbstractSigner` for Externally Owned Accounts (EOAs). Useful with ERC-7702.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/long-hornets-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableMap`: Add support for `BytesToBytesMap` type.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/lucky-donuts-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`ERC7739`: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/nice-rings-wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`ERC7913P256Verifier` and `ERC7913RSAVerifier`: Ready to use ERC-7913 verifiers that implement key verification for P256 (secp256r1) and RSA keys.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/pink-dolls-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableSet`: Add support for `StringSet` and `BytesSet` types.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/popular-geese-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`GovernorNoncesKeyed`: Extension of `Governor` that adds support for keyed nonces when voting by sig.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/proud-tables-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`ERC7739Utils`: Add a library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on the ERC-7739.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/public-crabs-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`MultiSignerERC7913Weighted`: Extension of `MultiSignerERC7913` that supports assigning different weights to each signer, enabling more flexible governance schemes.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/quiet-kiwis-feel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`SignerERC7913`: Abstract signer that verifies signatures using the ERC-7913 workflow.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/rare-shirts-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Arrays`: Add `unsafeAccess`, `unsafeMemoryAccess` and `unsafeSetLength` for `bytes[]` and `string[]`.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/rich-cows-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`InteroperableAddress`: Add a library for formatting and parsing ERC-7930 interoperable addresses.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/ripe-bears-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`ERC20Bridgeable`: Implementation of ERC-7802 that makes an ERC-20 compatible with crosschain bridges.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/rotten-apes-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`IERC7821`, `ERC7821`: Interface and logic for minimal batch execution. No support for additional `opData` is included.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/social-walls-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`MultiSignerERC7913`: Implementation of `AbstractSigner` that supports multiple ERC-7913 signers with a threshold-based signature verification system.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/sour-pens-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`SignatureChecker`: Add support for ERC-7913 signatures alongside existing ECDSA and ERC-1271 signature verification.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/strong-points-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`AccountERC7579Hooked`: Extension of `AccountERC7579` that implements support for ERC-7579 hook modules.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/tame-bears-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`AbstractSigner`, `SignerECDSA`, `SignerP256`, and `SignerRSA`: Add an abstract contract and various implementations for contracts that deal with signature verification.
5 changes: 5 additions & 0 deletions lib/openzeppelin-contracts/.changeset/wet-dodos-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Blockhash`: Add a library that provides access to historical block hashes using EIP-2935's history storage, extending the standard 256-block limit to 8191 blocks.
16 changes: 16 additions & 0 deletions lib/openzeppelin-contracts/.codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
comment: off
github_checks:
annotations: false
coverage:
status:
patch:
default:
target: 95%
only_pulls: true
project:
default:
threshold: 1%
ignore:
- "test"
- "contracts/mocks"
- "contracts/vendor"
21 changes: 21 additions & 0 deletions lib/openzeppelin-contracts/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = false
max_line_length = 120

[*.sol]
indent_size = 4

[*.js]
indent_size = 2

[*.{adoc,md}]
max_line_length = 0
10 changes: 10 additions & 0 deletions lib/openzeppelin-contracts/.github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# List of approvers/reviewers for OpenZeppelin Contracts
#
# Get in touch with us via the OpenZeppelin Forum
# https://forum.openzeppelin.com/
#
# Learn about CODEOWNERS file format:
# https://help.github.com/en/articles/about-code-owners

# These owners will be the default owners for everything in the repo.
* @OpenZeppelin/contracts
Loading
Loading