| title | Primitive Data Types |
|---|---|
| layout | default |
Clarity is a strongly-typed language where every value has a specific type. Understanding primitive data types is fundamental to writing Clarity smart contracts. This guide covers all primitive types available in Clarity with practical examples.
Clarity enforces strict type safety:
- No implicit type conversion - You cannot mix types in operations
- Compile-time type checking - Type errors are caught before deployment
- 128-bit integers - All integer types are 128-bit for precision
- Fixed-length sequences - Strings, buffers, and lists have maximum lengths
Unsigned integers represent non-negative whole numbers from 0 to 2^128 - 1.
Syntax: Prefix with u
u0 ;; Zero
u42 ;; Forty-two
u1000000 ;; One millionArithmetic Operations:
(+ u10 u5) ;; Returns u15
(- u20 u8) ;; Returns u12
(* u3 u7) ;; Returns u21
(/ u100 u4) ;; Returns u25 (integer division, no decimals)
(/ u10 u3) ;; Returns u3 (truncates decimal)
(mod u10 u3) ;; Returns u1 (remainder/modulo)Comparison Operations:
(> u10 u5) ;; Returns true
(< u3 u8) ;; Returns true
(>= u10 u10) ;; Returns true
(<= u5 u7) ;; Returns true
(is-eq u5 u5) ;; Returns true (equality check)Common Use Cases:
- Token amounts
- Counters and indices
- Block heights
- Timestamps
- IDs and identifiers
Signed integers represent both positive and negative whole numbers from -2^127 to 2^127 - 1.
Syntax: No prefix (just the number, with optional - for negative)
0 ;; Zero
42 ;; Positive forty-two
-100 ;; Negative one hundred
1000000 ;; Positive one millionArithmetic Operations:
(+ 10 5) ;; Returns 15
(- 20 30) ;; Returns -10
(* -3 7) ;; Returns -21
(/ 100 4) ;; Returns 25
(/ -10 3) ;; Returns -3 (truncates toward zero)Important: You cannot mix signed and unsigned integers!
(+ 2 u3) ;; ERROR: Type mismatch!
(* u5 10) ;; ERROR: Type mismatch!Common Use Cases:
- Relative changes (deltas)
- Temperature or coordinate systems
- Balance adjustments (positive/negative)
Booleans represent truth values: true or false.
true
falseLogical Operations:
(not true) ;; Returns false
(not false) ;; Returns true
(and true true) ;; Returns true
(and true false) ;; Returns false
(and true true true) ;; Returns true (multiple arguments)
(or false false) ;; Returns false
(or true false) ;; Returns true
(or false true false) ;; Returns true (multiple arguments)Comparison Results:
(is-eq u5 u5) ;; Returns true
(> u10 u5) ;; Returns true
(< 3 8) ;; Returns trueCommon Use Cases:
- Feature flags
- Access control checks
- Conditional logic
- State indicators
Principals represent Stacks addresses - either standard principals (users) or contract principals.
Standard Principal:
'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QEContract Principal:
'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.my-contractSpecial Keywords:
tx-sender ;; The principal that sent the transaction
contract-caller ;; The principal that called this functionWorking with Principals:
;; Check STX balance
(stx-get-balance 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE)
;; Transfer STX
(stx-transfer? u1000 tx-sender 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE)
;; Compare principals
(is-eq tx-sender contract-caller)Common Use Cases:
- Ownership and access control
- Token transfers
- User identification
- Contract interactions
ASCII strings contain basic Latin characters with a fixed maximum length.
Syntax:
"Hello World"
"This is an ASCII string"Type Declaration:
(string-ascii 50) ;; ASCII string with max length 50String Operations:
;; Concatenation
(concat "Hello" " World") ;; Returns "Hello World"
(concat "Hello, " (concat "Bob" "!")) ;; Returns "Hello, Bob!"
;; Length
(len "Hello") ;; Returns u5
;; Converting to UTF-8
(to-consensus-buff? "Hello") ;; Converts to bufferCommon Use Cases:
- Simple messages
- Names and labels
- ASCII-only data
- Token symbols
UTF-8 strings support international characters and special symbols.
Syntax: Prefix with u
u"Hello World"
u"Café"
u"Buenos días"
u"Привет"Type Declaration:
(string-utf8 100) ;; UTF-8 string with max length 100String Operations:
;; Concatenation
(concat u"Hello" u" 世界")
;; Length (in characters, not bytes)
(len u"Hello World") ;; Returns u11Common Use Cases:
- International applications
- User-generated content
- Multi-language support
- Non-ASCII characters
Buffers represent raw byte sequences with a fixed maximum length.
Syntax: Prefix with 0x followed by hexadecimal
0x68656c6c6f ;; "hello" in hex
0x00 ;; Single zero byte
0x1234567890 ;; Arbitrary bytesType Declaration:
(buff 32) ;; Buffer with max length 32 bytesBuffer Operations:
;; Length in bytes
(len 0x68656c6c6f) ;; Returns u5
;; Concatenation
(concat 0x1234 0x5678) ;; Returns 0x12345678
;; Converting strings to buffers
(to-consensus-buff? "hello") ;; Returns buffer representationCommon Use Cases:
- Cryptographic operations
- Hash values
- Binary data
- Serialization
While not primitive, these types build on primitives:
Represents success or failure of an operation.
(ok u100) ;; Success with value u100
(err u404) ;; Error with code u404
(ok true) ;; Success with boolean
(err "Not found") ;; Error with messageRepresents a value that may or may not exist.
(some u42) ;; Contains value u42
(some "Hello") ;; Contains string
(some tx-sender) ;; Contains principal
none ;; No value;; Same types - OK
(+ u10 u20) ;; Returns u30
(+ 10 20) ;; Returns 30
(concat "Hello" " World") ;; Returns "Hello World";; Mixing signed and unsigned - ERROR
(+ u10 20) ;; ERROR: Type mismatch
;; Mixing string types - ERROR
(concat "ASCII" u"UTF8") ;; ERROR: Type mismatch
;; Wrong comparison types - ERROR
(> u10 true) ;; ERROR: Cannot compare uint with bool-
Use Unsigned Integers by Default
- Most blockchain values are non-negative (balances, amounts, IDs)
- Use
uintunless you specifically need negative numbers
-
Choose the Right String Type
- Use
string-asciifor simple English text (more efficient) - Use
string-utf8when you need international support
- Use
-
Always Specify Maximum Lengths
- Strings:
(string-ascii 100) - Buffers:
(buff 32) - This prevents unbounded growth
- Strings:
-
Use Constants for Magic Numbers
(define-constant MAX-SUPPLY u1000000) ;; Good ;; Instead of using u1000000 directly ;; Bad
-
Type Annotations in Function Signatures
(define-public (transfer (amount uint) (recipient principal)) ;; Implementation )
;; Check for overflow before addition
(define-read-only (safe-add (a uint) (b uint))
(let ((result (+ a b)))
(asserts! (>= result a) (err u1))
(ok result)
)
);; Convert string to buffer
(to-consensus-buff? "hello")
;; Note: No direct uint to int conversion
;; Design your contract to use one type consistently;; Default value for missing data
(define-read-only (get-balance-safe (account principal))
(default-to u0 (map-get? balances account))
)
;; Unwrap with panic (use carefully!)
(unwrap-panic (some u42)) ;; Returns u42