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))