全局存储操作

全球存储操作 #

Move 程序可以使用以下五个指令在全局存储中创建、删除和更新资源:

OperationDescriptionAborts?
move_to<T>(&signer,T)Publish T under signer.addressIf signer.address already holds a T
move_from<T>(address): TRemove T from address and return itIf address does not hold a T
borrow_global_mut<T>(address): &mut TReturn a mutable reference to the T stored under addressIf address does not hold a T
borrow_global<T>(address): &TReturn an immutable reference to the T stored under addressIf address does not hold a T
exists<T>(address): boolReturn true if a T is stored under addressNever

这些指令中的每一条都由具有关键能力的类型 T 参数化。但是,每个类型 T 都必须在当前模块中声明。这确保资源只能通过其定义模块公开的 API 进行操作。这些指令还采用地址 &signer 表示存储类型 T 资源的帐户地址。

module my_addrx::counter {
    use std::signer;
    use std::account;

    /// Resource that wraps an integer counter
    struct Counter has key { i: u64 }

    /// Publish a `Counter` resource with value `i` under the given `account`
    public fun publish(account: &signer, i: u64) {
      // "Pack" (create) a Counter resource. This is a privileged operation that
      // can only be done inside the module that declares the `Counter` resource
      move_to(account, Counter { i })
    }

    /// Read the value in the `Counter` resource stored at `addr`
    public fun get_count(addr: address): u64 acquires Counter {
        borrow_global<Counter>(addr).i
    }

    /// Increment the value of `addr`'s `Counter` resource
    public fun increment(addr: address) acquires Counter {
        let c_ref = &mut borrow_global_mut<Counter>(addr).i;
        *c_ref = *c_ref + 1
    }

    /// Reset the value of `account`'s `Counter` to 0
    public fun reset(account: &signer) acquires Counter {
        let c_ref = &mut borrow_global_mut<Counter>(signer::address_of(account)).i;
        *c_ref = 0
    }

    /// Delete the `Counter` resource under `account` and return its value
    public fun delete(account: &signer): u64 acquires Counter {
        // remove the Counter resource
        let c = move_from<Counter>(signer::address_of(account));
        // "Unpack" the `Counter` resource into its fields. This is a
        // privileged operation that can only be done inside the module
        // that declares the `Counter` resource
        let Counter { i } = c;
        i
    }

    /// Return `true` if `addr` contains a `Counter` resource
    public fun resource_exists(addr: address): bool {
        exists<Counter>(addr)
    }

    #[test(admin = @0x123)]
    public entry fun test_flow(admin: signer) acquires Counter 
    {
        account::create_account_for_test(signer::address_of(&admin));
        
        publish(&admin,5);
        assert!(get_count(signer::address_of(&admin))==5,1);
        increment(signer::address_of(&admin));
        assert!(get_count(signer::address_of(&admin))==6,1);
        reset(&admin);
        assert!(get_count(signer::address_of(&admin))==0,1);
        delete(&admin);
        assert!(resource_exists(signer::address_of(&admin))==false,1);
    }
}

在计数器示例中,您可能已经注意到 get_countincrementresetdelete 函数被注释为 acquires Counter。当且仅当:

  • m::f 的主体包含 move_from<T>borrow_global_mut<T>borrow_global<T> 指令,或
  • m::f 的主体调用在同一个模块中声明的函数 m::g,该模块用 acquires 注释。