Variables
Variables are data members that can be changed over time. They are only modifiable by the current smart contract. Variables have a predefined type and an initial value.
(define-data-var var-name var-type initial-value)
Where the var-type is a type signature and initial-value a valid value for
the specified type. Although you can name a variable pretty much anything, you
should be mindful of the built-in keywords. Do not use
keywords as variable names.
Variables can be read using the function var-get and changed using var-set.
;; Define an unsigned integer data var with an initial value of u0.
(define-data-var my-number uint u0)
;; Print the initial value.
(print (var-get my-number))
;; Change the value.
(var-set my-number u5000)
;; Print the new value.
(print (var-get my-number))
Notice the uint? That is the type signature.
Type signatures
The chapter on types covered how to express a value of a specific type. Type signatures, on the other hand, define the admitted type for a variable or function argument. Let us take a look at what the signatures look like.
| Type | Signature |
|---|---|
| Signed integer | int |
| Unsigned integer | uint |
| Boolean | bool |
| Principal | principal |
| Buffer | (buff max-len), where max-len is a number defining the maximum length. |
| ASCII string | (string-ascii max-len), where max-len is a number defining the maximum length. |
| UTF-8 string | (string-utf8 max-len), where max-len is a number defining the maximum length. |
| List | (list max-len element-type), where max-len is a number defining the maximum length and element-type a type signature. Example: (list 10 principal). |
| Optional | (optional some-type), where some-type is a type signature. Example: (optional principal). |
| Tuple | {key1: entry-type, key2: entry-type}, where entry-type is a type signature. Every key can have its own type. Example: {sender: principal, amount: uint}. |
| Response | (response ok-type err-type), where ok-type is the type of returned ok values and err-type is the type of returned err values. Example: (response bool uint). |
We can see that some types indicate a maximum length. It goes without saying
that the length is strictly enforced. Passing a value that is too long will
result in an analysis error. Try changing the following example by making the
"This works." string too long.
(define-data-var message (string-ascii 15) "This works.")
Like other kinds of definition statements, define-data-var may only be used at
the top level of a smart contract definition; that is, you cannot put a define
statement in the middle of a function body.
Remember that whitespace can be used to make your code more readable. If you are defining a complicated tuple type, simply space it out:
(define-data-var high-score
;; Tuple type definition:
{
score: uint,
who: (optional principal),
at-height: uint
}
;; Tuple value:
{
score: u0,
who: none,
at-height: u0
}
)
;; Print the initial value.
(print (var-get high-score))
;; Change the value.
(var-set high-score
{score: u10, who: (some tx-sender), at-height: block-height}
)
;; Print the new value.
(print (var-get high-score))