Sway 合约如何用 storage namespace 注解避免存储槽位冲突?
Sway 合约如何用 storage namespace 注解避免存储槽位冲突【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway在 Sway 中编写合约时存储槽位storage slot的键由变量名等位置信息哈希计算得出。当合约以加载代码的方式与其他合约共享同一存储空间时两个合约里同名或同位置的存储变量可能落到同一个槽位上互相覆盖对方的值。Sway 官方文档给出的对策是 storage namespace存储命名空间在storage块里声明一个具名命名空间块编译器会为槽位键的计算加入 salt让命名空间内的变量被定位到不同的存储位置。本文基于仓库中的文档与示例项目走一遍从声明命名空间、读写其中变量到编译验证的完整路径。什么时候需要 storage namespaceAdvanced Storage 文档 对 namespace 一节的原始表述是如果你希望存储中的值定位到不同的位置——例如在加载代码时避免与另一个合约的存储发生冲突——可以使用 namespace 注解为槽位计算加入 salt。也就是说它的适用边界很明确目标不是改变存储 API而是改变变量在存储中的定位典型场景是多份合约代码加载进同一个存储上下文时防止槽位互相覆盖。参考文档 Namespace 章节 给出了槽位键的计算方式位于命名空间my_namespace中的变量foobar其位置由sha256(storage::my_namespace.foobar)的哈希计算决定。变量名被拼进了哈希输入这正是命名空间起到隔离作用的机制。同一文档还说明命名空间可以作用于storage块也可以作用于放在命名空间内部的变量一个storage块内可以顺序放置多个命名空间也支持嵌套。声明命名空间与声明变量的写法按参考文档中的示例最简声明如下storage { my_storage_namespace { var: u64 0, } }其中my_storage_namespace是命名空间名var: u64 0是该命名空间内带初始值的存储变量。命名空间内变量的读写命名空间内变量通过storage::命名空间.变量路径访问。参考文档给出的读、写示例#[storage(read)] fn read() { let variable storage::my_storage_namespace.var.read(); } #[storage(write)] fn write() { storage::my_storage_namespace.var.write(storage::my_storage_namespace.var.read() 1); }访问存储读/写操作的函数需要对应的#[storage(read)]、#[storage(write)]注解这也是该示例文件的原样写法。一个完整的示例合约仓库的 examples/storage_namespace 给出了完整的可编译合约包含命名空间声明、ABI 与实现contract; use std::storage::storage_api::{read, write}; storage { example_namespace { foo: u64 0, }, } abi StorageNamespaceExample { #[storage(write)] fn store_something(amount: u64); #[storage(read)] fn get_something() - u64; } impl StorageNamespaceExample for Contract { #[storage(write)] fn store_something(amount: u64) { storage.foo.write(amount); } #[storage(read)] fn get_something() - u64 { storage.foo.try_read().unwrap_or(0) } }对应的 Forc.toml 依赖配置[project] authors [Fuel Labs contactfuel.sh] entry main.sw license Apache-2.0 name storage_namespace [dependencies] std { path ../../sway-lib-std }注意std的path ../../sway-lib-std是相对仓库根目录布局写的如果把这份示例拷到自己项目里这个相对路径需要按你的实际 std 位置替换。另外两处访问写法可以对照看参考文档使用storage::my_storage_namespace.var完整路径而示例合约在 impl 中写的是storage.foo两者都是仓库文档与示例中的原样用法。构建与验证最小验证路径是在项目目录内执行编译forc build编译通过即说明storage块、命名空间块与存储注解语法正确。更深的验证可以参考仓库自带的 e2e 测试程序 test_contracts/storage_namespace。该合约在my_storage_namespace命名空间内声明了u64、str、u256、b256等多种变量其test_storage()函数对每个变量做写入—回读—断言的往返检查例如assert_eq(storage::my_storage_namespace.c1.read(), C1); storage::my_storage_namespace.c1.write(2); assert_eq(storage::my_storage_namespace.c1.read(), 2);测试入口#[test] fn call_test_storage_exhaustive()通过 ABI 调用合约的test_storage_exhaustive触发上述检查。这份测试程序也展示了命名空间内变量的标准访问形式storage::命名空间.变量。边界与限制namespace 只影响槽位键的哈希计算给键加入命名空间 salt不改变read/write等存储 API 本身命名空间内的变量依然按storage块的常规语法声明和访问。一个storage块内可以有多个命名空间顺序排列或嵌套参考文档说明但文档没有给出多命名空间场景下的额外示例命名冲突的具体处理以编译器行为为准。文档中关于 storage 的其余限制例如数组尚不能在storage块中声明只能借助StorageMapK, V属于 storage 块整体约束与 namespace 无关此处不展开如需查阅见 Advanced Storage 文档 的 Manual Storage Management 一节。【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考