ismael6499/evm-upgradeable-proxies
GitHub: ismael6499/evm-upgradeable-proxies
基于 Solidity 的 EVM 可升级智能合约参考实现,涵盖 UUPS 代理模式、EIP-1967 存储槽隔离与升级状态保持。
Stars: 0 | Forks: 0
# 🔄 EVM 可升级性与代理架构(UUPS vs Transparent)




以太坊虚拟机(EVM)上可升级智能合约架构的参考实现,重点关注**通用可升级代理标准(UUPS / EIP-1822)**、**EIP-1967 存储槽**以及**存储冲突缓解**。
## 📌 上下文 vs 实现
### 1. 传统软件部署 vs EVM 不可变性
* **传统后端(Java/Spring):** 更新服务逻辑涉及通过 CI/CD 推送新的容器部署。内存布局和数据库模式动态演变。
* **EVM 智能合约:** 部署在某个地址上的字节码是不可变的。可升级性需要使用代理委托将**状态(Storage)**与**逻辑(字节码执行)**分离开来。
### 2. 执行委托(`delegatecall`)
当用户调用 Proxy 合约时,Proxy 会向 Implementation 逻辑合约执行 `delegatecall`:
* **上下文:** 代码从 Implementation 地址加载,但完全在 Proxy 的 storage、余额和 `msg.sender` 上下文中执行。
* **存储对齐:** `VaultV2` 中的 storage 变量布局必须严格扩展 `VaultV1` 的 storage 布局,且不能重新排序现有的插槽,以防止灾难性的 storage 损坏。
```
+------------------+ +-----------------------+
| Proxy Contract | -- delegatecall ->| Implementation (V1/V2)|
| (Storage & ETH) | | (Pure Logic) |
+------------------+ +-----------------------+
```
## 🛠️ 技术亮点
### EIP-1967 存储槽隔离
为了防止 Implementation 逻辑变量与 Proxy 内部状态变量之间发生冲突,Implementation 地址存储在固定的伪随机插槽中:
```
// Implementation Slot: bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
```
### 初始化器锁定模式
Constructor 在合约创建期间执行,但修改的是 Implementation 合约自身的 storage,而不是 Proxy 的。
* `VaultV1` 通过 `initialized = true` 锁定 constructor,以防止未初始化的 Implementation 被劫持。
* Proxy 的 storage 在部署时通过 `initialize(address _owner)` 进行初始化。
## 🧪 测试与验证
通过 Foundry 执行了单元测试和升级不变性验证:
```
forge test -vvv
```
### 已验证的测试向量
1. `test_InitialDeployment_Success`:验证 EIP-1967 代理初始化和初始 `V1` 逻辑。
2. `test_Deposit_Success`:验证在 Proxy storage 上下文内的状态写入。
3. `test_UpgradeToV2_PreservesState`:将逻辑指针从 `V1` 升级到 `V2`,验证用户余额、所有权和 ETH 总量在升级后保持 100% 完整。
标签:EVM存储隔离, Foundry测试, Solidity, UUPS代理模式, 区块链, 可升级合约, 智能合约