Proxy

- 1 min

透明代理 transparent(最常用)

代理合约的执行原理:

当无法匹配函数selector的时候, 函数会调用fallback/receive,接着会使用delegatecall调用逻辑合约

为什么用fallback而不是receive, receive能干的事情也就2300gas

msg.data != null and receive exites => call receive

什么是msg.data, 其实就是calldata, 也就是selector + input params组合

函数选择器 = bytes4 = 8 * 2^16

selector = bytes4(keccak256(“burn(uint256)”));

如果出现同一个合约两个函数的选择器一样, 那么就不会通过编译

if 逻辑合约的a函数 = 代理合约的升级函数

管理人通过代理调用a函数的时候, 就会把代理合约升级成一个黑洞合约, 因为选择器是一样的嘛

那么我们禁止管理员调用任何逻辑合约的函数, 就能解决这个问题. (在fallback中校验)

这样做的缺点:

每次都要检查, 消耗多余gas

arch

graph TD
    A[User] -->|Calls| B[Proxy Contract]
    B -->|Forwards Call| C[Implementation Contract]
    B -->|Admin| D[Admin Account]
    subgraph Proxy Contract
        direction LR
        B1[Storage Slot for Admin Address]
        B2[Storage Slot for Implementation Address]
    end
    C -->|Handles Logic| E[Contract Logic]

flow

sequenceDiagram
    participant User
    participant Proxy
    participant LogicContract
    participant NewLogicContract

    User->>Proxy: 调用合约函数
    Proxy->>LogicContract: 转发函数调用
    LogicContract->>Proxy: 返回函数结果
    Proxy->>User: 返回函数结果

    User->>NewLogicContract: 升级逻辑合约请求
    NewLogicContract->>Proxy: 设置新的逻辑合约地址
    Proxy->>User: 升级成功提示

    User->>Proxy: 调用合约函数(已升级)
    Proxy->>NewLogicContract: 转发函数调用
    NewLogicContract->>Proxy: 返回函数结果
    Proxy->>User: 返回函数结果

UUPS的代理合约(TODO)

如何解决逻辑合约的函数和代理合约的升级函数的选择器冲突呢?

把升级函数放入逻辑合约中.

通过这样的方式, 把数据都存在了代理合约上, 逻辑合约不存储任何东西, 但是必须保持两个合约的插槽一样, 否则引起冲突.

arch

graph TD;
    client[("Client<br>(Ethereum User)")] -->|calls| proxy[("Proxy Contract<br>(Storage + Address of Implementation)")]
    proxy -->|delegates call to| implementation[("Implementation Contract v1<br>(Logic + Upgrade Functionality)")]
    implementation -->|can be upgraded to| new_implementation[("Implementation Contract v2<br>(New Logic + Upgrade Functionality)")]

subgraph UUPS Proxy
    direction LR
        B1[implementation: address]
        B2[admin: address]
        B3[__self: immutable address]
end

flow

sequenceDiagram
    participant User
    participant UUPSProxy
    participant LogicContract

    User->>UUPSProxy: 调用升级函数
    UUPSProxy->>LogicContract: 获取当前逻辑合约地址
    LogicContract-->>UUPSProxy: 返回当前逻辑合约地址
    UUPSProxy->>UUPSProxy: 验证升级权限
    UUPSProxy->>UUPSProxy: 获取新逻辑合约地址
    UUPSProxy->>LogicContract: 设置新逻辑合约地址
    LogicContract-->>UUPSProxy: 升级结果
    UUPSProxy-->>User: 返回升级结果