Skip to main content

Command Palette

Search for a command to run...

Variables & Constants & Collection Overview

Updated
9 min readView as Markdown
T
Founder & Architect of Blsqui. Building the cloud-native infrastructure layer that transforms standard video games into instant Web3 eSports platforms. Passionate about democratizing global revenue networks for the next generation of independent, AI-driven creators. Creating plug-and-play, no-code backend frameworks for Unity and Godot that integrate frictionless stablecoin microtransactions without client-side execution overhead.

Variables and Constants

How to declare

let represents a constant, and var represents a variable.

pub fun main {
   var a: Int = 2 // Regular types cannot contain nil (null).
   var a: Int? = nil // To allow variables to hold nil, use an Optional Type.
   var b Int = a!  // To convert an Optional type to a regular variable, use !. (In this case, it's nil, so it will result in an error.)
}

In Cadence, it is common to convert an optional type to a regular type. Using optional binding (the if let statement) simplifies this process, as the variable within the if let block is no longer optional.


Types

Boolean type

let boolVar: Bool = true

Int type

let int8: Int8 = 127 // -128~127
let int16: Int16 = 32767 // -32768~32767
let int32: Int32 = 2147483647 // -2147483648~2147483647
let int64: Int64 = 9223372036854775807 // -9223372036854775808~9223372036854775807
let int128: Int128 = 9223372036854775808 // -2^127~2^127 − 1
let int256: Int256 = 9223372036854775808 // -2^255~2^255 − 1

UInt type

let uint8: UInt8 = 255 // 0~255
let uint16: UInt16 = 65535 // 0~65535
let uint32: UInt32 = 4294967295 // 0~4294967295
let uint64: UInt64 = 18446744073709551615 // 0~18446744073709551615
let uint128: UInt128 = 18446744073709551616 // 0~2^128 − 1
let uint256: UInt256 = 18446744073709551616 // 0~2^256 − 1

Arbitrary-precision type (Int/UInt)

let integer: Int = 1 // Arbitrary-precision (unbounded)
let uinteger: UInt = 1 // Arbitrary-precision (unbounded)

Word type

Unsigned integer types that do not perform overflow or underflow checks, i.e., those that wrap around, have the prefix “Word” and can represent values within the following range.

let nilWord: Word8? = Word8.fromString("1024") // nil, out of bounds, 0~255
let word16: Word16? = Word16.fromString("255") // 0~65535
let word32: Word32? = Word32.fromString("255") // 0~4294967295
let word64: Word64? = Word64.fromString("255") // 0~18446744073709551615

Fix / UFix type

let fix64: Fix64? = Fix64.fromString("-0.1") // ok, -92233720368.54775808~92233720368.54775807
let ufix64: UFix64? = UFix64.fromString("-0.1") // nil, 0.0~184467440737.09551615

Address type

let some: Address = 0x436164656E636521 // UInt64 length. (Max:18446744073709551615)

AnyStruct / AnyResource type

All types are classified as either AnyStruct or AnyResource. The AnyStruct type can represent all types except for Resource types.

var someStruct: AnyStruct = 1 // Can represent all types except Resource type
var someResource: @AnyResource <- create TestResource()

Always prefix the resource type with the @ directive. Use the <- operator for moves.


Never type

 let x: Never = nil

Return type of the panic function


Character / String type

let char: Character = "\u{FC}"
let someString: String = "Hello, world!"

Functions for each type

Int / Address type functions

/* Convert a number to a string */
let int8Number: Int8 = 127
let int8str String = int8Number.toString()


/* Returns a byte array in big-endian order */
let largeNumber: Int32 = 1234567890
let arr: [UInt8] = largeNumber.toBigEndianBytes() //[73, 150, 2, 210]


/* Convert a string to a number */
let int8str: String = "42"
let int8number: Int64? = Int64.fromString(int8str)


/* Return the maximum value of a number */
let max = UInt8.max // 255


/* Return the minimum value of a number */
let min = UInt8.min // 0


/* Convert a FixedPointNumber to a string */
let fix64number: Fix64 = 1.23
let fix64str String = fix64number.toString()


/* Convert an Address to a string */
let shortAddress: Address = 0x1
let str: String = shortAddress.toString()  // "0x0000000000000001"


/* Convert an Address to a UInt8 array */
let someAddress: Address = 0x436164656E636521
someAddress.toBytes()  // is [67, 97, 100, 101, 110, 99, 101, 33]

String type functions

/* Get the length of a string */
let example: String = "hello"
let length: Int = example.length // 5


/* Convert a string to a byte array using UTF8 encoding */
let str: String = "hello"
let utf8: [UInt8] = str.utf8()


/* Concatenate strings */
let str1 = "hello"
let str2 = "world"
let helloWorld = str1.concat(str2) // "helloworld"


/* Get a part of a string */
let example = "helloworld"
let slice = example.slice(from: 3, upTo: 6) // "low"


/* Convert a string to a byte array represented as a hexadecimal string */
let example = "436164656e636521"
example.decodeHex() // is [67, 97, 100, 101, 110, 99, 101, 33]


/* Convert a string to lowercase */
let example = "Flowers"
example.toLower() // `flowers`


/* Convert a byte array to a hexadecimal string */
let data = [1 as UInt8, 2, 3, 0xCA, 0xDE]
String.encodeHex(data) // is "010203cade"


/* Get one character from a string */
let str = "abc"
let c: Character = str[0] // is the Character "a"

Character type functions

/* Convert a character to a string */
let c: Character = "x"
c.toString()  // is "x"


/* Convert an array of characters to a string */
let rawUwU: [Character] = ["U", "w", "U"]
let uwu: String = String.fromCharacters(rawUwU) // "UwU" 

Collection Types

Array type

How to declare

They can be declared within contract, struct, or resource types, as well as within transaction code. When defined within a smart contract, initialization via init is required.

access(all) contract SampleContract {
    access(contract) var allNames: [String]
    init() {
      self.allNames = []
    }
 }

A Contract is also a type, but in this case, the address where it is deployed is included as part of the type definition. Consequently, Struct and Resource types are never confused with types defined within other Contracts.


Array type functions

/* Retrieve the length of an array */
self.allNames.length


/* Concatenate arrays */
self.allNames.concat(allNames2)


/* Check if an array contains a value */
self.allNames.contains("Kitty")


/* Add a value to array */
self.allNames.append("Jane") // This function mutates the array.


/* Add multiple values to an array */
self.allNames.appendAll("Jane", "Daisy") // This function mutates the array.


/* Get the index of a value in an array */
self.allNames.firstIndex(of: "Daisy")


/* Get a portion of an array */
self.allNames.slice(from: 1, upTo: 3)


/* Insert a value at any position in an array */
self.allNames.insert(at: 2, "Daisy") // This function mutates the array.


/* Remove a value from an array */
self.allNames.remove(at: 1) // This function mutates the array.


/* Remove the first value from an array */
self.allNames.removeFirst() // This function mutates the array.


/* Remove the last value from an array */
self.allNames.removeLast() // This function mutates the array.

Dictionary type

How to declare

They can be declared within contract, struct, or resource types, as well as within transaction code. When defined within a smart contract, initialization via init is required.

access(all) var luckeyNumbers: {String: Int}
init() {
  self.luckeyNumbers = {}
}

When self is referenced within a struct type, it represents the struct type; within a resource type, it represents the resource type; and within a contract, it represents the contract type.


Dictionary type functions

/* Insert a value */
self.luckeyNumbers["Daisy"] = 7


/* ・If you want to raise an error when "Daisy" is not present in `luckeyNumbers`, you can achieve this by using a `pre` block. */
pre {
    self.luckeyNumbers.contains("Daisy"): "Not in luckeyNumbers"
}


/* Get all keys from a Dictionary */
self.luckeyNumbers.keys


/* Get all values from a Dictionary */
self.luckeyNumbers.values // This method cannot be used with a Dictionary containing resources (resources cannot be moved without the <- operator).


/* Insert a value at any position in a Dictionary */
self.luckeyNumbers.insert(key: "Jessica", 42) // If a value already exists, it is returned as an Optional type.


/* Retrieve a value from a Dictionary */
self.luckeyNumbers.remove(key: "Joe") // If a value is present, it returns that value as an Optional type; otherwise, it returns nil.


/* Check if a Dictionary contains a value */
self.luckeyNumbers.containsKey("Kitty")


/* Iterates over all keys in the Dictionary */
self.luckeyNumbers.forEachKey(fun (key: String): Bool {
    // The returned boolean value signals whether to continue
    // true = `continue`
    // false = `break`
    return true
})

pre and post blocks

The pre{} block contains validation logic to be checked before the transaction is executed,

while the post{} block contains validation logic to verify the transaction's validity immediately before it is included in the blockchain.

As the name implies, the pre block is used to verify the validity of values ​​at the beginning of a method. If a value is invalid, a panic (transaction failure) occurs, and the string following the colon (:) is displayed in the transaction result output.

Similarly, the post block is used to verify the validity of values ​​at the end of a method. If a value is invalid, a panic (transaction failure) occurs, and the string following the colon (:) is displayed in the transaction result output.

pre and post blocks can also be used in transaction code; transaction processing proceeds in the order: prepare block -> pre block -> execute block -> post block. (In principle, anything that can be written in a smart contract—except for event declarations—can also be written in transaction code.)


event

You can declare it within the smart contract and invoke it during transaction execution; it can be called from either a smart contract or transaction code. When invoking it, you can pass arguments of the types specified in the event declaration, and by monitoring these in Go or JavaScript, you can track what is happening. Retrieving events is slightly more complex than retrieving blockchain information based on a transaction ID.