Address & Signer

Address

Summary

  • Address is a 256-bit identifier representing locations in global storage in Move.
  • Addresses can store Modules and Resources, but are intentionally opaque and don't support arithmetic operations.
  • Address syntax includes named and numerical forms, with @ prefix in expression contexts.
  • Signer represents authority over blockchain resources and is used for transaction execution.
  • Signer values are automatically generated by the Move VM and cannot be created through literals.
  • The std::signer module provides utility functions for working with signers.
  • Addresses are primarily used for global storage operations, while signers are used for transaction authorization.

Address Overview

Address is an integrated data type in Move used to represent locations (sometimes referred to as accounts) in global storage. An address value is a 256-bit (32-byte) identifier. At a specific address, two things can be stored: a Module and a Resource.

Although an address is a 256-bit integer, Move addresses are designed to be intentionally opaque; they cannot be derived from integers, do not support arithmetic operations, and cannot be altered. While there may be interesting programs utilizing such features (for example, pointer operators in C serve a similar role), Move does not allow such dynamic behavior as it is designed from the ground up to support static verification.

You can use address values at runtime (address-type values) to access resources at that address. You cannot access modules at runtime through address values.

Address and Syntax:

Addresses have two forms: named or numerical. The syntax of named addresses follows the same rules as any identifier name in Move. The syntax of numerical addresses is not limited to hexadecimal values, and any valid u256 numeric value can be used as an address value; for example, 40, 0xCAFE, and 2024 are all valid numeric address literals.

To distinguish when an address is being used in the context of an expression or not, the syntax for using an address varies depending on the context in which it is used:

  • When an address is used as an expression, it must be prefixed by the character @, for example: @<numerical_value> or @<named_address_identifier>.
  • Outside of expression contexts, an address can be written without the prefix @, for example: <numerical_value> or <named_address_identifier>.

Declaring Address Variables

let addr1: address = @0x1;      //numerical address example
let addr2: address = @my_addrx; //named address example

Primary purpose

  • The primary purpose of addresses is to interact with global storage operations.
  • Address values are used with the operations exists, borrow_global, borrow_global_mut, and move_from.
  • The only global storage operation that does not use an address is move_to, which uses a signer instead.

Signer

Signer Overview

Signer is a data type that represents the authority and control over a resource or asset on the blockchain. The signer data type is used to designate which account or entity is responsible for executing a specific transaction or operation on the blockchain.

You can think of its native implementation as follows:

struct signer has drop { a: address }

Declaring Signer Variables

Signer values are special because they cannot be created through literals or instruction-only constructs that can be generated by the Move VM. Before the VM executes a script with parameters of the signer type, it will automatically generate signer values and pass them into the code:

module movement::address_and_signer {
    use std::signer;

    // All structures that are saved to global storage must include the key attribute
    struct ResourceName has key {
        data: u64,
    }

    fun create_resource(new_data: u64, owner: &signer) {
        move_to(owner, ResourceName{
            data: new_data
        });
    }
}

signer Operations: The package std::signer in the standard library module provides 2 utility functions for signer:

  • signer::address_of(&signer): address - Returns the address wrapped by &signer.
  • signer::borrow_address(&signer): &address - Returns a reference to the address wrapped by &signer.
module movement::address_and_signer {
    use std::signer;
    use std::debug::print;

    // All structures that are saved to global storage must include the key attribute
    struct ResourceName has key {
        data: u64,
    }

    public entry fun create_resource(owner: &signer, new_data: u64) {
        move_to(owner, ResourceName{
            data: new_data
        });
        print(owner); // signer
        print(&signer::address_of(owner)); // address of signer
    }

    #[test(account = @0x1)]
    fun test_create_resource(account: &signer) {
        create_resource(10, account);
    }
}

Running test

movement move test -f address_and_signer
  • Result:
Running Move unit tests
[debug] @0x1
[debug] signer(@0x1)
[ PASS ] 0xdb8a45e0e06d2bd305cdb824fda101cec6a24721cb03188c5543a5e5a8c3f3b0::address_and_signer::test_create_resource
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
  "Result": "Success"
}

Publish & call on blockchain

  • Publish Modules
movement aptos publish
  • Call Function
movement move run --function-id 'default::address_and_signer::create_resource' --args u64:10
  • Check it on your account list with command:
movement account list
  • In the returned result, you will see an object similar to the one below:
{
  "0x5fdf6936671d4e4a89b686aff0b5a4dfe083babbaaa6e78f5daa8801f94938a6::address_and_signer::ResourceName": {
    "data": "10"
  }
}