Skip to content

Commit 3d03a84

Browse files
author
Ryan
committed
Updated README.md
1 parent 042b012 commit 3d03a84

2 files changed

Lines changed: 174 additions & 91 deletions

File tree

README.md

Lines changed: 172 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,176 @@
22

33
**ProxyForge** is a lightweight, gas-optimized framework for deploying and managing upgradeable proxies on the Ethereum Virtual Machine (EVM). It maintains compatibility with OpenZeppelin's proxy architecture while introducing low-level optimizations and slot-based metadata tracking.
44

5-
---
6-
75
## Features
86

9-
- **Transparent Proxy** — Transparent proxy pattern (`ERC1967` compatible)
10-
- **Proxy Admin** — Upgrade proxies securely using minimal admin logic
11-
- **Factory Deployment** — Deploy proxies via `CREATE` and `CREATE2`
12-
- **Slot-Based Tracking** — No mappings, storage traced via keccak256 seeds
13-
- **Modular Design** — Components can be used independently or via the factory
7+
- **Transparent Proxy Pattern**: ERC-1967 compliant with admin isolation for security
8+
- **Assembly Optimized**: Extensive use of inline assembly for maximum efficiency
9+
- **Gas-Optimized Deployments**: Highly efficient CREATE and CREATE2 proxy deployments
10+
- **Comprehensive Management**: Deploy, upgrade, transfer ownership, and revoke proxies
11+
- **Deterministic Addresses**: CREATE2 support with collision-resistant salt validation
12+
- **Modular Design**: Components can be used independently or via the factory
13+
14+
## Architecture
15+
16+
### Directory
17+
18+
```text
19+
proxy-forge/
20+
├── deployments/...
21+
├── script/
22+
│ ├── BaseScript.sol
23+
│ ├── Deploy.s.sol
24+
│ ├── DeployProxy.s.sol
25+
│ └── UpgradeProxy.s.sol
26+
├── src/
27+
│ ├── interfaces/
28+
│ │ ├── IForgeProxy.sol
29+
│ │ ├── IForgeProxyAdmin.sol
30+
│ │ └── IProxyForge.sol
31+
│ ├── proxy/
32+
│ │ ├── ForgeProxy.sol
33+
│ │ └── ForgeProxyAdmin.sol
34+
│ └── ProxyForge.sol
35+
└── test/
36+
├── proxy/
37+
│ ├── ForgeProxy.t.sol
38+
│ └── ForgeProxyAdmin.t.sol
39+
├── shared/...
40+
├── ProxyForge.fuzz.t.sol
41+
└── ProxyForge.t.sol
42+
```
1443

15-
---
44+
### Core Contracts
1645

17-
## Contracts Overview
46+
**ProxyForge**: The main factory contract that handles deployment and management operations
1847

19-
| Contract | Description |
20-
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21-
| **ForgeProxy** | The core proxy contract that delegates calls to implementation contracts. Features assembly-optimized routing and automatic admin deployment. |
22-
| **ForgeProxyAdmin** | Ultra-lightweight admin contract for managing proxy upgrades. Automatically deployed per proxy with minimal overhead, enabling isolated upgrade control. |
23-
| **ProxyForge** | The central hub for proxy deployment and management. Provides multiple deployment strategies via factory methods, including deterministic and non-deterministic paths. |
48+
- Deploys new proxy instances using CREATE or CREATE2
49+
- Manages proxy ownership and implementation upgrades
50+
- Provides deterministic address computation
2451

25-
---
52+
**ForgeProxy**: Gas-optimized upgradeable proxy implementation
2653

27-
## API Reference
54+
- Follows ERC-1967 standard for storage slots
55+
- Automatic admin contract deployment during construction
56+
- Assembly-optimized fallback routing for maximum efficiency
2857

29-
### Deployment Flow
58+
**ForgeProxyAdmin**: Ultra-lightweight admin contract for proxy management
3059

31-
1. Call `deploy()` or `deployAndCall()` on `ProxyForge`.
32-
2. A `ForgeProxy` is deployed with the specified implementation and (optionally) initialized via delegatecall.
33-
3. A `ForgeProxyAdmin` is auto-deployed and linked to the proxy.
34-
4. Proxy ownership, admin, and implementation are tracked via factory-local slot logic.
60+
- Handles upgrade operations with calldata transformation
61+
- Implements standard ownership patterns
62+
- Compatible with OpenZeppelin ProxyAdmin interface (v5.0.0)
3563

36-
### Usage Snippet
64+
## Deployments
3765

38-
```solidity
39-
// Deploy via CREATE without initialization
40-
address proxy = proxyForge.deploy(implementation, owner);
66+
**ForgeProxy** is deployed on the following chains:
67+
68+
| Network | Chain ID | Address |
69+
| ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
70+
| Ethereum | 1 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://etherscan.io/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
71+
| Ethereum Sepolia | 11155111 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://sepolia.etherscan.io/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
72+
| Optimism | 10 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://optimistic.etherscan.io/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
73+
| Polygon | 137 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://polygonscan.com/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
74+
| Base | 8453 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://basescan.org/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
75+
| Base Sepolia | 84532 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://sepolia.basescan.org/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
76+
| Arbitrum One | 42161 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://arbiscan.io/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
77+
| Arbitrum Sepolia | 421614 | [0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe](https://sepolia.arbiscan.io/address/0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe) |
78+
79+
## Usage
80+
81+
### Installation
82+
83+
#### Foundry
84+
85+
```bash
86+
forge install fomoweth/proxy-forge
87+
```
88+
89+
#### Clone
90+
91+
```bash
92+
git clone https://github.com/fomoweth/proxy-forge.git
93+
```
94+
95+
### Build
96+
97+
```bash
98+
forge build --sizes
99+
```
100+
101+
### Test
102+
103+
```bash
104+
# Run all tests
105+
forge test
106+
107+
# Run with detailed logs
108+
forge test -vvv
109+
110+
# Run with gas reporting
111+
forge test --gas-report
112+
113+
# Run specific test
114+
forge test --match-path test/ProxyForge.fuzz.t.sol
115+
```
116+
117+
### Deploy
41118

42-
// Deploy via CREATE and initialize in one tx
43-
address proxy = proxyForge.deployAndCall(implementation, owner, data);
119+
#### To Deploy Contract
44120

45-
// Deploy deterministically via CREATE2 without initialization
46-
address proxy = proxyForge.deployDeterministic(implementation, owner, salt);
121+
```bash
122+
forge script \
123+
script/Deploy.s.sol:Deploy \
124+
-vvv \
125+
--slow \
126+
--multi \
127+
--broadcast
128+
```
129+
130+
#### To Verify Contract
47131

48-
// Deploy deterministically via CREATE2 and initialize in one tx
49-
address proxy = proxyForge.deployDeterministicAndCall(implementation, owner, salt, data);
132+
```bash
133+
forge verify-contract <CONTRACT_ADDRESS> \
134+
src/ProxyForge.sol:ProxyForge \
135+
--compiler-version v0.8.30+commit.73712a01 \
136+
--verifier etherscan \
137+
--etherscan-api-key <ETHERSCAN_API_KEY> \
138+
--chain-id <CHAIN_ID>
139+
```
50140

51-
// Upgrade existing proxy
52-
proxyForge.upgrade(proxy, implementation);
141+
### Basic Usage
53142

54-
// Upgrade existing proxy with initialization
55-
proxyForge.upgradeAndCall(proxy, implementation, data);
143+
```solidity
144+
import {IProxyForge} from "lib/proxy-forge/interfaces/IProxyForge.sol";
145+
146+
contract MyContract {
147+
IProxyForge public constant PROXY_FORGE = IProxyForge(0x58b819827cB18Ba425906C69E1Bfb22F27Cb1bCe);
148+
149+
function deployProxy(address implementation) external returns (address proxy) {
150+
// Deploy a new proxy with msg.sender as owner
151+
return PROXY_FORGE.deploy(implementation, msg.sender);
152+
}
153+
154+
function deployProxy(address implementation, uint96 identifier) external returns (address proxy) {
155+
// Create a deterministic salt (first 20 bytes must be caller or zero address)
156+
bytes32 salt = bytes32((uint256(uint160(msg.sender)) << 96) | uint256(identifier));
157+
// Deploy with CREATE2 for deterministic address
158+
return PROXY_FORGE.deployDeterministic(implementation, msg.sender, salt);
159+
}
160+
161+
function deployProxy(address implementation, bytes memory data) external returns (address proxy) {
162+
// Encode initialization call data
163+
bytes memory initData = abi.encodeWithSignature("initialize(bytes)", data);
164+
// Deploy and initialize in one transaction
165+
return PROXY_FORGE.deployAndCall(implementation, msg.sender, initData);
166+
}
167+
}
56168
```
57169

58-
### Deployment Functions
170+
## API Reference
171+
172+
### Core Functions
173+
174+
#### Deployment Functions
59175

60176
```solidity
61177
function deploy(address implementation, address owner) external payable returns (address proxy);
@@ -64,87 +180,52 @@ function deployDeterministic(address implementation, address owner, bytes32 salt
64180
function deployDeterministicAndCall(address implementation, address owner, bytes32 salt, bytes calldata data) external payable returns (address proxy);
65181
```
66182

67-
### Management Functions
183+
#### Management Functions
68184

69185
```solidity
70186
function upgrade(address proxy, address implementation) external payable;
71187
function upgradeAndCall(address proxy, address implementation, bytes calldata data) external payable;
72-
function setProxyOwner(address proxy, address owner) external payable;
188+
function revoke(address proxy) external payable;
189+
function changeOwner(address proxy, address owner) external payable;
73190
```
74191

75-
### View Functions
192+
#### View Functions
76193

77194
```solidity
78-
function getProxyOwner(address proxy) external view returns (address owner);
79-
function getProxyAdmin(address proxy) external view returns (address admin);
80-
function getProxyImplementation(address proxy) external view returns (address implementation);
81-
82-
function computeProxyAddress(address implementation, bytes32 salt, bytes calldata data) external view returns (address proxy);
195+
function adminOf(address proxy) external view returns (address admin);
196+
function implementationOf(address proxy) external view returns (address implementation);
197+
function ownerOf(address proxy) external view returns (address owner);
83198
function computeProxyAddress(uint256 nonce) external view returns (address proxy);
84-
function computeProxyAdminAddress(address proxy) external view returns (address admin);
199+
function computeProxyAddress(address implementation, bytes32 salt, bytes calldata data) external view returns (address proxy);
85200
```
86201

87202
### Events
88203

89204
```solidity
90205
event ProxyDeployed(address indexed proxy, address indexed owner, bytes32 indexed salt);
91206
event ProxyUpgraded(address indexed proxy, address indexed implementation);
92-
event ProxyAdminChanged(address indexed proxy, address indexed admin);
93-
event ProxyImplementationChanged(address indexed proxy, address indexed implementation);
94207
event ProxyOwnerChanged(address indexed proxy, address indexed owner);
208+
event ProxyRevoked(address indexed proxy);
95209
```
96210

97-
---
98-
99-
## Testing
100-
101-
This project includes a Foundry-based test suite that verifies:
102-
103-
- Deployment paths (`CREATE`, `CREATE2`)
104-
- Admin upgrade controls
105-
- Proxy delegatecall correctness
106-
- Storage slot consistency
107-
- Revert conditions and unauthorized access
108-
109-
Run tests with:
110-
111-
```bash
112-
# Run all tests
113-
forge test
114-
115-
# Run with detailed logs
116-
forge test -vvv
211+
### Errors
117212

118-
# Run with gas reporting
119-
forge test --gas-report
120-
121-
# Run specific test
122-
forge test --match-path test/ProxyForge.fuzz.t.sol
213+
```solidity
214+
error InvalidProxy();
215+
error InvalidProxyImplementation();
216+
error InvalidProxyOwner();
217+
error InvalidSalt();
218+
error UnauthorizedAccount(address account);
219+
error UpgradeFailed();
123220
```
124221

125-
---
126-
127-
## Deployment
128-
129-
**ForgeProxy** is deployed on the following chains:
130-
131-
| Network | Chain ID | Address |
132-
| ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
133-
| Sepolia | 11155111 | [0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9](https://sepolia.etherscan.io/address/0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9) |
134-
| Arbitrum Sepolia | 421614 | [0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9](https://sepolia.arbiscan.io/address/0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9) |
135-
| Base Sepolia | 84532 | [0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9](https://sepolia.basescan.org/address/0x5bbbb378546a9b1dB3d6a2FaCa37E3B93dBB03b9) |
136-
137-
---
138-
139222
## Acknowledgements
140223

141-
Inspired by:
224+
The following repositories served as key references during the development of this project:
142225

143-
- [OpenZeppelin TransparentUpgradeableProxy](https://github.com/OpenZeppelin/openzeppelin-contracts)
226+
- [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)
144227
- [Solady](https://github.com/Vectorized/solady)
145228

146-
---
147-
148229
## Author
149230

150-
- [@fomoweth](https://github.com/fomoweth)
231+
- [fomoweth](https://github.com/fomoweth)

foundry.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ fs_permissions = [
2222
{ access = "read", path = "./test"}
2323
]
2424

25+
gas_reports = ["ProxyForge", "ForgeProxy", "ForgeProxyAdmin"]
26+
2527
remappings = [
2628
"forge-std/=lib/forge-std/src/",
2729
"createx/=lib/createx/src"

0 commit comments

Comments
 (0)