StarknetAstro

StarknetAstro

Scalar types in 03_Cairo (felt, integer, boolean, float)

Scalar types in Cairo (felt, integer, boolean, float)#

The version of the Cairo compiler used in this article is 2.0.0-rc0. Since Cairo is being rapidly updated, there may be slight differences in syntax between different versions, and the article content will be updated to the stable version in the future.

felt252#

felt252 is a basic type in Cairo, representing a storage slot. Literal values without a specified variable type default to felt252. felt252 can be a negative number or zero, and its range is:

-2^251 < felt < 2^251 + 17* 2^192 + 1

Any value within this range can be stored in felt252. Note: it is not -2^251 to 2^251 - 1.

felt252 can store both integers and strings. Here are examples of storing integers and strings:

use debug::PrintTrait;

fn main() {
    // Declare using the let keyword and assign a literal value, the default type should be felt252
    let x: felt252 = 5;
    let y: felt252 = 'ppppppppppppppppppppppppppp';
    let z: felt252 = 'ppppppppppppppppppppppppppp99999999999999'; // Overflow
    x.print();
}

Note: It is 252, not 256, and adding other numbers after felt or not adding any number will result in a compilation error, for example, felt256 felt.

Short Strings#

Short strings are represented by single quotes and cannot exceed 31 characters in length. Short strings are essentially of type felt252, but they are represented as strings. Computers convert characters to numbers using the ASCII protocol. The length of a short string cannot exceed the maximum value of felt252.

let mut my_first_initial = 'C';

Difference between felt252 and integers#

In Cairo 1.0, felt252 does not support division or modulo operations, but integers do.

Here is a description of felt in Cairo 0.1:

"Flet" is short for "field elements" and can be translated as "field elements". The difference between felt252 and integers is mainly reflected in division operations. When an operation that cannot be evenly divided occurs, such as 7/3, the result of integer division is usually 2, but not for felt252. felt252 will always satisfy the equation x3 = 7. Since it can only be an integer, the value of x3 will be a huge integer, causing an overflow, and the overflow value happens to be 7.

In Cairo 1.0, division using felt252 is prohibited:

use debug::PrintTrait;

fn main() {
    let x = 7 / 3;
    x.print();
}

// The above code will result in the following error
error: Trait has no implementation in context: core::traits::Div::<core::felt252>
 --> f_felt252.cairo:4:13
    let x = 7 / 3;
            ^***^

Error: failed to compile: src/f_felt252.cairo

Integers#

The core library includes the following integer variables: u8, u16, u32 (usize), u64, u128, and u256. They are all implemented using felt252 and come with integer overflow detection. When declaring an integer variable without specifying its type, the default type is felt252. Here is an example:

let y = 2;

To specify u8, u16, etc., the variable type needs to be indicated:

let x:u8 = 2;

The u256 type is more complex and requires the use of other types to construct it. In the core library, u256 is a structure with two fields, high and low, both of which are of type u128. Since a storage slot (felt252) cannot hold u256 data, it needs to be split into two storage slots for storage.

let z: u256 = u256 { high: 0, low: 10 }

This involves the concept of the high address segment and the low address segment. If you are interested, you can search for related information.

Operators#

Integers support most operators and come with overflow detection. They support the following:

fn test_u8_operators() {
    // Calculation
    assert(1_u8 + 3_u8 == 4_u8, '1 + 3 == 4');
    assert(3_u8 + 6_u8 == 9_u8, '3 + 6 == 9');
    assert(3_u8 - 1_u8 == 2_u8, '3 - 1 == 2');
    assert(1_u8 * 3_u8 == 3_u8, '1 * 3 == 3');
    assert(2_u8 * 4_u8 == 8_u8, '2 * 4 == 8');
    assert(19_u8 / 7_u8 == 2_u8, '19 / 7 == 2');
    assert(19_u8 % 7_u8 == 5_u8, '19 % 7 == 5');
    assert(231_u8 - 131_u8 == 100_u8, '231-131=100');

    // Comparison
    assert(1_u8 == 1_u8, '1 == 1');
    assert(1_u8 != 2_u8, '1 != 2');
    assert(1_u8 < 4_u8, '1 < 4');
    assert(1_u8 <= 4_u8, '1 <= 4');
    assert(5_u8 > 2_u8, '5 > 2');
    assert(5_u8 >= 2_u8, '5 >= 2');
    assert(!(3_u8 > 3_u8), '!(3 > 3)');
    assert(3_u8 >= 3_u8, '3 >= 3');
}

Similarly, u256 also supports these operators:

use debug::PrintTrait;

fn main() {
    let x:u256 = u256{high:3, low: 3};
    let y:u256 = u256{high:3, low: 3};

    let z = x + y;
    assert(z == 2 * y, 'z == 2 * y');
    assert(0 == x - y, '0 == x - y');
    assert(1 == x / y, '0 == x - y');
    assert(0 == x % y, '0 == x % y');

    assert(x == y, 'x == y');
    assert(x <= y, 'x <= y');
    assert(x >= y, 'x <= y');
    assert(x - 1 < y, 'x - 1 < y');
    assert(x + 1 > y, 'x + 1 >= y');
    assert(x != y - 1, 'x != y');
}

Boolean#

Boolean values can be declared using the following syntax:

let is_morning:bool = true;
let is_evening:bool = false;

Float#

Not supported yet.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.