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
61177function deploy(address implementation, address owner) external payable returns (address proxy);
@@ -64,87 +180,52 @@ function deployDeterministic(address implementation, address owner, bytes32 salt
64180function 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
70186function upgrade(address proxy, address implementation) external payable;
71187function 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);
83198function 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
90205event ProxyDeployed(address indexed proxy, address indexed owner, bytes32 indexed salt);
91206event 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);
94207event 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 )
0 commit comments