Solidity Tutorial : All about Value Types.
Solidity is a statically typed language, which means that we need to specify the type of each variable.
In Solidity, data types can be broadly classified into two categories according to data location. If a variable store its own data; it is a value type. If it holds a location of the data; it is a reference type. In this article, we will examine the various value types that are present in solidity.
Lets get a clearer definition of value types;
A value type is a type that holds the data directly in the memory owned by it. Variables of these types are always passed by value, meaning that they are always copied when assigned to another variable or passed into a function.
The following types are value types in Solidity:
- Booleans
- signed integers
- unsigned integers
- addresses
- fixed-size byte arrays (
bytes1
tobytes32
) - Enums
- fixed point numbers (they are not fully supported yet)
Boolean values are represented by bool and have only two possible values namely;
true
andfalse
. Solidity supports all your regular Boolean operators, such as!
,&&
,==
etc. They only take up 1 byte of storage.
Example: bool public a_boolean;
The integer type is denoted by keywords uint8 to uint256 and int8 to int256 for unsigned
and signed
integers in increment of 8 respectively. uint
and int
are aliases for uint256
and int256
respectively and both take up 32 bytes by default. If you know your variable will never hold that many bytes you can always make it smaller by explicitly specifying the number of bits. For example int128
/uint128
.
Integers in Solidity are restricted to a certain range, if assigned values outside the range you get either an overflow or underflow error . For example, with uint32
, this is 0
up to 2**32 - 1
and the same applies in terms of calculating the range of any other size. Also note that the unsigned integer cannot carry the positive or negative sign while signed integer can.
The operations which we can perform on integers are –
- Comparisons:
<=
,<
,==
,!=
,>=
,>
(result value isbool
) - Bit operators:
&
,|
,^
(bitwise exclusive or),~
(bitwise negation) - Shift operators:
<<
(left shift),>>
(right shift) - Arithmetic operators:
+
,-
, unary-
(only for signed integers),*
,/
,%
,**
The address type is something that is unique to solidity. It is a data type to store a 20-byte value representing the Ethereum address. The address type comes in two versions, namely, address and address payable.
address
: address type holds a 20 byte value (size of an Ethereum address).address payable
: it is same asaddress
, but with the additional memberstransfer
andsend
.
The main difference between these two types is that address payable
is an address you can send Ether to, while a plain address
cannot be sent Ether.
Type conversions:
We can implicitly convert from address payable
to address
, whereas conversions from address
to address payable
must be explicitly done via payable(<address>)
.
Explicit conversions to and from address
are allowed for uint160
, integer literals, bytes20
and contract types.
You declare an address like this: address public an_address;
Fixed-size byte arrays
Fixed-size byte arrays contain a sequence of bytes. The length of the array must always be specified in the type declaration. They are declared in the following way bytes1
, bytes2
, bytes3
all the way up to bytes32
. byte
is an alias for bytes1
. You can use your regular boolean operators, comparison operators, and bitwise operators on this type too.
It’s important to note that there is another type, called bytes
which is different from the above in that it is a dynamically sized array, and not a value type but a reference type. It is basically shorthand for byte[]
.
When you can limit the length of your data to a predefined amount of bytes, it is always good practice to use some of bytes1
to bytes32
because it is much cheaper.
Also note that the difference between bytes and strings is that bytes stores values in an array like [ “e”]. Because bytes
are treated as array is Solidity code, it can have a length of zero and you can do things like append a byte to the end. You can push, pop and length, however, bytes is not a value type !
You declare a byte variable like this: bytes32 samevar = “stringliteral”;
Enums in Solidity are a way to create user-defined types. Enums are explicitly convertible to integer types, but not implicitly. Enum values are numbered in the order they are defined, starting from 0.
Enums are not part of the ABI (Application Binary Interface — it’s basically how you encode Solidity code for the Ethereum Virtual Machine, and how you get data back). This means that if your function returns an enum
for example, it will be automatically converted to a uint8
behind the scenes. The integer returned is just large enough to hold all enum values. With more values, the size gets increased too (uint16
and up).
Fixed point numbers are similar to float data type but the main difference is that we need to specify the number of bits required for the integer part and fractional part in fixed-point numbers whereas, in float, it is not necessary.
We use fixed/ufixed keywords to specify fixed-point numbers of various sizes. We need to specify the fixed-point numbers in the following manner — fixedMxN
and ufixedMxN
. Here M
represents the number of bits taken by the type and N
represents how many decimal points are available.
Solidity does not fully support Fixed Point numbers yet, hence we can declare Fixed Point numbers but we cannot assign them to or from them.
The operations available for fixed-point numbers are –
- Comparisons:
<=
,<
,==
,!=
,>=
,>
- Arithmetic operators:
+
,-
, unary-
,*
,/
,%
Conclusion
In this lesson, we looked at what value types are available in Solidity and how each one works. To learn more look up the solidity documentation by clicking here.