![]() |
|
[Tut] Solidity Contract Types, Byte Arrays, and {Address, Int, Rational} Literals - Printable Version +- Sick Gaming (https://sickgaming.net) +-- Forum: Programming (https://sickgaming.net/forum-76.html) +--- Forum: Python (https://sickgaming.net/forum-83.html) +--- Thread: [Tut] Solidity Contract Types, Byte Arrays, and {Address, Int, Rational} Literals (/thread-100027.html) |
[Tut] Solidity Contract Types, Byte Arrays, and {Address, Int, Rational} Literals - xSicKxBot - 10-05-2022 Solidity Contract Types, Byte Arrays, and {Address, Int, Rational} Literals 5/5 – (1 vote) With this article, we continue our journey through the realm of Solidity data types following today’s topics:
It’s part of our long-standing tradition to make this (and other) articles a faithful companion or a supplement to the official Solidity documentation. Download PDF Slide Deck at the end of this tutorial!Contract Types ![]() To quote the official Solidity documentation, “every contract defines its own type”. This statement might seem a bit cryptic, and since we’re an efficient crowd, we’d surely like to know what it means. We can all remember that some number of articles ago, we mentioned how Solidity has key elements of an object-oriented programming language (OOPL). We also emphasized how smart contracts in Solidity are very similar to classes in an OOPL. Classes themselves are a mesh of custom data types, i.e. structs, and functions, which qualifies classes to be treated as types. By extension, our contracts are also treated as types, and as every contract is unique in its own right, it defines its own type. Being a type, we can implicitly convert a specific contract to a contract it inherits from, i.e. if contract “Aa” inherits from contract A, it can also be converted to contract “A”.![]() Besides that, we can explicitly convert each contract to and from the address type. Even more, we can conditionally convert a contract to and from the Code: address payableCode: addressThe condition is that the contract type must have a Code: receiveCode: payableCode: address(x)However, if the contract type does not implement (a more professional way to say “have”) a Code: receiveCode: payableCode: payable(address(x))A local variable Code: obcCode: OurBeautifulContractCode: OurBeautifulContract obc;Once we point our variable Code: obcIn terms of its data representation, a contract is identical to the Code: addressIn contrast to the types mentioned so far, contract types don’t support any operators. The members of contract types are the external functions (the functions only available to other contracts) and state variables whose visibility is set to Code: publicWhen we need to access type information about the contract, like the Code: OurBeautifulContractCode: type(OurBeautifulContract)Fixed-Size Byte Arrays ![]() The value type Code: bytesNCode: NCode: bytes1Code: bytes32The available operators for fixed-size operators are:
The shifting operator always uses an unsigned integer type as a right operand, which represents the number of bits to shift by, and returns the type of the left operand. Let’s take a look at a simple example to illustrate: Code: bytes2 lo = 0x1234; // (lo is the left operand)
uint8 ro = 5; // (ro is the right operand variable, must be u... type)
lo << ro // will evaluate to an lo type, bytes2A fixed-size byte array has only one member, .length, that holds the fixed length of the byte array. This member is accessible as the read-only value. Warning: Since the type Code: bytes1Code: bytes1[]Code: bytesCode: bytes1[] Note: Value types in storage are packed/compacted together and share a storage slot, taking only as much space per value type as really needed. In contrast, the stack, memory, and Code: calldataBefore Solidity v0.8.0, the keyword Code: byteCode: bytes1Dynamically-Sized Byte Arrays ![]() There are two dynamically-sized non-value types, namely Code: bytesCode: string
Address Literals Address literals are hexadecimal literals that pass the address checksum test, e.g. Code: 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AFHexadecimal literals will produce an error if they are between 39 and 41 digits long and do not pass the checksum test. However, we can remove the error by prepending zeros to integer types or appending zeros to Code: bytesNNThe Ethereum Improvement Proposal EIP-55 defines the mixed-case address checksum. Integer and Rational Literals Integer Literals Integer literals are created using a sequence of digits from a range 0-9, and each digit is interpreted (weighted) based on its position in the sequence. Multiplied by an exponent of 10, e.g. 217 is interpreted as two hundred and seventeen, because, reading from right to left, we have 7 * 100 + 1 * 101 + 2 * 102. A reminder, 100 = 1. Octal literals don’t exist in Solidity and leading zeros are invalid. Decimal Fractional Literals Decimal fractional literals consist of a dot Code: .Code: 1.Code: .1Code: 1.3 Info: “A locale consists of a number of categories for which country-dependent formatting or other specifications exist” (source).Scientific Notation Solidity also supports scientific notation in the form of 2e10, where 2 (left of “e”) is called mantissa (M) and the exponent (E) must be an integer. In a general form, we would write it as MeE and it is interpreted as M * 10**E, e.g. 2e10, -2e10, 2e-10, 2.5e1. Readable Underscore Notation ![]() We can also do a neat thing: separate the digits of a numeric literal for easier readability, such as in decimal Code: 123_000Code: 0x2eff_abdeCode: 1_2e345_678However, there are no leading, trailing, or multiple underscores; they can only be added between two digits. Number Literal Expressions Expressions containing number literals preserve their precision until they are converted to a non-literal type. Such a conversion means an explicit conversion, or that the number literals are used with something else than a number literal expression, like boolean literals. This behavior implies that computations don’t overflow and divisions don’t truncate in number literal expressions. A very good example would be a number literal expression (2**800 + 1) – 2**800, which results in the constant 1 (of type Code: uint8One more example shows that an integer 4 is produced by computing the expression Code: .5 * 8More Operations Warning: most operators produce a literal expression when applied to number literals, but there are also two exceptions:
In other words, expressions like Code: 255 + (true ? 1 : 0)Code: 255 + [1, 2, 3][0]Code: uint8Number literal expressions can use the same operators as the integers, but both operands must compute yield an integer.
Shifts and exponentiation Code: *Code: (base*Code: exponent*Code: uint256Code: int256Code: * Warning: Since Solidity v0.4.0 division on integer literals produces a rational number, e.g. 7 / 2 = 3.5.Solidity has a number literal types for each rational number, e.g. integer literals and rational number literals belong to the same number literal type. All number literal expressions (expressions with only number literals and operators) also belong to number literal types, e.g. 1 + 2 and 2 + 1 belong to the same number literal type. Note: When number literal types are used with non-literal expressions, they are converted into a non-literal type, e.g. Code: uint128 a = 1; uint128 b = 2.5 + a + 0.5;Here, 1 is converted into a non-literal type Code: uint128Code: aCode: 2.5Code: uint128Conclusion In this article, we added even more data types in Solidity under our proverbial belt!
Slide Deck Data Types You can scroll through the data types discussed in this tutorial here: Solidity-Overview-Data-Types-MoreDownload |