闲社服务运行正常AI智能体自动化平台
u

升级Stylus合约

技能标识:upgrade-stylus-contracts

Upgrade Stylus smart contracts using OpenZeppelin proxy patterns on Arbitrum. Use when users need to: (1) make Stylus Rust contracts upgradeable with UUPS or Beacon proxies, (2) understand Stylus-specific proxy mechanics (logic_flag, WASM reactivation), (3) integrate UUPSUpgradeable with access control, (4) ensure storage compatibility across upgrades, or (5) test upgrade paths for Stylus contracts.

作者:admin | 来源记录:ClawHub
登记来源
ClawHub
版本
V 1.0.1
检测标记
后台标记通过
免费
免费获取
0
收藏
来源与检测标记为平台登记信息,并不代表已展示可复核的检测报告。使用前请核对版本、依赖和所需权限,建议先在隔离环境中运行。
概述
安装方式
版本历史

升级Stylus合约

Stylus 升级

目录

Stylus 升级模型

Stylus 合约在 Arbitrum 上作为 WebAssembly (WASM) 程序与 EVM 并行运行。它们与 Solidity 合约共享相同的状态树、存储模型和账户系统。因此,EVM 代理模式对 Stylus 完全适用——Solidity 代理可以委托给 Stylus 实现,反之亦然。

StylusSolidity
代理机制相同——通过 delegatecall 调用实现合约通过 delegatecall 调用实现合约
存储布局
#[storage] 字段映射到与等效 Solidity 结构体相同的 EVM 存储槽 | 按 Solidity 规则顺序分配存储槽 |
| EIP 标准 | ERC-1967 存储槽、ERC-1822 可代理 UUID | 相同 |
| 上下文检测 | 在唯一存储槽中使用 logic_flag 布尔值(不支持 immutable) | 将 address(this) 存储为 immutable |
| 初始化 | 两步:构造函数设置 logicflag,然后通过代理调用 setversion() | 通过代理执行构造函数 + 初始化函数 |
| 重新激活 | WASM 合约必须每 365 天或在 Stylus 协议升级后重新激活 | 不适用 |

现有的 Solidity 合约可以通过代理模式升级到 Stylus (Rust) 实现。#[storage] 宏在 EVM 状态树中布局字段的方式与 Solidity 完全相同,因此当类型定义匹配时,存储槽会保持一致。

代理模式

OpenZeppelin Stylus 合约提供三种代理模式:

模式关键类型最佳用途
UUPSUUPSUpgradeable、IErc1822Proxiable、Erc1967Proxy大多数项目——升级逻辑在实现中,代理更轻量
Beacon
BeaconProxy、UpgradeableBeacon | 多个代理共享一个实现——更新 Beacon 可原子化升级所有代理 |
| 基础代理 | Erc1967Proxy、Erc1967Utils | 自定义代理模式的底层构建块 |

注意: OpenZeppelin Stylus 合约目前不提供透明代理模式。请使用 UUPS(推荐用于大多数项目)。

UUPS

实现合约在其 #[storage] 结构体中组合 UUPSUpgradeable 和访问控制(例如 Ownable)。集成需要:

  1. 1. 在 #[storage] 结构体中添加 UUPSUpgradeable(和访问控制)作为字段
  2. 在构造函数中调用 self.uups.constructor() 并初始化访问控制
  3. 暴露 initialize 函数,调用 self.uups.setversion()——部署后通过代理调用
  4. 实现 IUUPSUpgradeable——upgradetoandcall 受访问控制保护,upgradeinterfaceversion 委托给 self.uups
  5. 实现 IErc1822Proxiable——proxiable_uuid 委托给 self.uups

代理合约是一个轻量的 Erc1967Proxy,其构造函数接受实现地址和初始化数据,并包含一个将所有调用委托出去的 #[fallback] 处理器。

使用 set_version 作为初始化调用数据部署代理。使用 cargo stylus deploy 或部署合约。初始化数据是 ABI 编码的 setVersion 调用:

rust
let data = MyContractAbi::setVersionCall {}.abi_encode();
// 在部署时将 data 作为代理构造函数的第二个参数传入。

Beacon

多个 BeaconProxy 合约指向一个存储当前实现地址的 UpgradeableBeacon。更新 Beacon 可在一次交易中升级所有代理。

上下文检测(Stylus 特有)

Stylus 不支持 immutable 关键字。UUPSUpgradeable 不使用 self = address(this),而是在唯一存储槽中使用 logic_flag 布尔值:

  • - 实现的构造函数在其自身存储中设置 logicflag = true。
  • 当代码通过代理运行时(delegatecall),代理的存储中不包含此标志,因此读取为 false。
  • onlyproxy() 检查此标志,确保升级函数只能通过代理调用,而不能直接在实现上调用。

onlyproxy() 还会验证 ERC-1967 实现槽非零,并且代理存储的版本与实现的 VERSIONNUMBER 匹配。

示例: 请参阅 rust-contracts-stylus 仓库 的 examples/ 目录,获取 UUPS、Beacon 及相关模式的完整工作集成示例。

访问控制

升级函数必须受访问控制保护。OpenZeppelin 的 Stylus 合约未将访问控制嵌入升级逻辑本身——您必须在 upgradetoand_call 中添加:

rust
fn upgradetoandcall(&mut self, newimplementation: Address, data: Bytes) -> Result<(), Vec> {
self.ownable.only_owner()?; // 或任何访问控制检查
self.uups.upgradetoandcall(newimplementation, data)?;
Ok(())
}

常见选项:

  • - Ownable——单一所有者,最简单的模式
  • AccessControl / RBAC——基于角色,更细粒度
  • 多签或治理——用于管理重要价值的生产合约

升级安全

存储兼容性

Stylus #[storage] 字段在 EVM 状态树中的布局方式与 Solidity 完全相同。升级时适用相同的存储布局规则:

  • - 切勿重新排序、删除或更改现有存储字段的类型
  • 切勿在现有字段之前插入新字段
  • 只能在结构体末尾追加新字段
  • ERC-1967 代理存储槽位于高位、标准化的位置——不会与实现存储冲突

与 Solidity 的一个区别:Stylus #[storage] 中的嵌套结构体(例如,将 Erc20、Ownable、UUPSUpgradeable 组合为字段)的布局中,每个嵌套结构体从其自身的确定性存储槽开始。这与 Solidity 中常规结构体嵌套一致,但与 Solidity 基于继承的扁平布局不同,后者所有继承变量共享一个连续的存储槽范围。

初始化安全

  • - 实现构造函数设置 logicflag 和任何仅实现状态。它在实现部署时运行一次。
  • setversion() 必须通过代理调用(在部署期间或通过 upgradetoandcall),以将 VERSIONNUMBER 写入代理的存储。
  • 如果需要额外初始化(所有权、代币供应),请暴露受保护的初始化函数并将 set_version() 包含在其中。
  • 初始化不当可能导致合约成为孤儿,没有所有者、状态未初始化或无法进行未来升级。

抢跑警告: 始终将初始化调用数据作为代理构造函数的一部分传递,以确保部署和初始化是原子化的(单笔交易)。切勿在单独的交易中部署代理和初始化——攻击者可以抢跑初始化调用,可能将自己设置为所有者或破坏初始状态。初始化函数应包含防止重新初始化的防护:
rust
// 重新初始化防护模式
fn initialize(&mut self, owner: Address) -> Result<(), Vec> {
if self.initialized.get() {
return Err(balready initialized.to_vec());
}
self.initialized.set(true);
self.uups.set_version();
self.ownable.init(owner)?;
Ok(())
}

如果没有这样的防护,初始化函数可以被多次调用,允许攻击者重新初始化合约并夺取所有权。

UUPS 升级检查

UUPS 实现强制执行三项安全检查:

  1. 1. 访问控制——限制 upgradetoandcall(例如 self.ownable.onlyowner())
  2. 代理上下文强制——如果调用不是通过 delegatecall 进行的,onlyproxy() 会回退
  3. 可代理 UUID 验证——proxiableuuid() 必须返回 ERC-1967 实现槽,确认 UUPS 兼容性

重新激活

Stylus WASM 合约必须每年重新激活一次(365 天)或在任何 Stylus 协议升级后重新激活。可以使用 cargo-stylus 或 ArbWasm 预编译进行重新激活。如果合约未重新激活,它将变得不可调用。这与代理升级正交,但必须纳入维护计划。

测试升级路径

在升级生产合约

标签

skill ai

通过对话安装

以下为平台配置的接入选项,并非逐项实测通过。能否安装取决于客户端支持、技能来源和运行环境:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 upgrade-stylus-contracts-1776077589 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 upgrade-stylus-contracts-1776077589 技能

通过命令行安装

skillhub install upgrade-stylus-contracts-1776077589

下载

⬇ 下载 upgrade-stylus-contracts v1.0.1(免费)

文件大小: 4.37 KB | 发布时间: 2026-4-15 14:48

v1.0.1 最新 2026-4-15 14:48
Fix display name from probe to proper title
返回顶部