# Solidity Fixed Point Numbers and Address Types (Howto)

With this article, we continue our journey through the realm of Solidity data types.

π Recommended Tutorial: Solidity Basic Data Types

This time, we will focus on fixed point numbers, address types and address type members, and investigate when, how, and why they are used.

Traditionally, our articles are running alongside the official Solidity documentation and are used to clarify, supplement, and explain the concepts laid out in the documentation.

## Fixed Point Numbers

β‘ Warning: Solidity still does not fully support fixed-point numbers, in that it allows only the declaration, but not the assignment from and to fixed point variables.

Fixed point numbers exist in the signed (`fixed`) and unsigned (`ufixed`) variants and sizes.

Keywords can be written in a general form of `ufixedMxN` and `fixedMxN`, where the parameter `M` represents the number of bits that our type takes, and the parameter `N` represents how many decimal points are reserved for our type.

As with the integer type, the parameter `M` starts with the value 8 and also increments in the steps of 8, up to the value of 256. The parameter `N` can be any integer between 0 and 80 (included).

If we express our fixed point type as `fixed` or `ufixed` (without the parameters `M` and `N`), it is interpreted as an alias for `fixed128x18` and `ufixed128x18`.

### Fixed Point Operators

Here we’ll list the available operators for fixed point types:

• Comparisons: `<=, <, ==, !=, >=, > `(evaluate to bool)
• Arithmetic operators: `+, -, unary -, *, /, %` (modulo)

### Fixed vs Floating Point Numbers

We have to make a point about the difference between floating point and fixed point numbers.

Floating point numbers usually correspond to float and double in many programming languages; technically speaking, they’re referred to as IEEE 754 numbers, named after their defining standard IEEE 754.

The main difference is that with the fixed point numbers, the number of bits used for the integer and the fractional part (after the decimal dot) is strictly defined, while with the floating point numbers the number of bits used for the integer and the fractional part is flexible.

In practice, floating point numbers take up almost the entire space to represent the number, and only a small number of bits will be used to define the location of the decimal point.

The address type is available in two variants, and they are almost identical but don’t worry, we’ll touch on the difference in a moment:

• `address`: The type is associated with a 20-byte value, which is a size of an Ethereum address.
• `address payable`: The type is the same as `address`, the only difference is that it has additional members `transfer(...)` and `send(...)`.

The difference between the two lies in a need to distinguish an address, i.e., to `address payable` we can send Ether, from a plain address that holds a smart contract not designed to receive Ether.

In other words, the two address types exist to prevent sending the currency to the wrong address, while we have to explicitly specify the right address.

Of course, in some cases, we’ll have to be able to convert the `address` type to the `address payable` type, and for that, we use the explicit conversion function `payable(<address>)`. Conversion in the other direction, i.e. from the address payable type to address type is implicit.

Explicitly conversions to and from the address type are allowed for `uint160`, integer literals (variants `int8/uint8` to `int256/uint256`), `bytes20`, and `contract` type.

Only variables of type `address` and `contract` type can be converted to the type `address payable` by using the explicit conversion function `payable(<address>)` and `payable(this)`. The keyword `this` is a reference to the current contract.

In case we’re converting a `contract` type, the contract must be able to receive Ether, i.e. it either has a `receive()` function or a `payable` fallback function.

However, there is an exception to the rule: the expression `payable(0)`.

π‘ Note: When we’re facing a requirement of needing an address variable and also plan to send Ether to this address, we should declare the `address` type as `address payable` as soon as possible to avoid any unnecessary conversions.

The operators available for use with the address type are the comparison operators:

• `<=` Less than or equal to
• `<` Less than
• `==` Equal to
• `!=` Not equal to
• `>=` Greater than or equal to
• `>` Greater than

Warning: since there is a possibility to convert a larger type, e.g. `bytes32` to an address, the address will be truncated. Solidity creators made a step in reducing this ambiguity since Solidity compiler v0.4.24, forcing us to explicitly truncate the larger type variable.

If we take a 32-byte value

`b = 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC`,

we can convert it by keeping the first 20 bytes, like in

`address(uint160(bytes20(b))) = 0x111122223333444455556666777788889999AAAA`,

or the last 20 bytes, like in

`address(uint160(uint256(b))) = 0x777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC`.

π‘ Note: The types `address` and `address payable` were introduced with Solidity v0.5.0. One more novelty that this version introduced was that the contracts stopped being derived from the `address` type, although they can still be explicitly converted to types `address` or `address payable`, but only if they have a `receive()` or `payable` fallback function.

π Recommended Tutorial: What is Solidity `payable`?

The two notable members of an `address` or `address payable` type are property `balance` and function `transfer(...)`.

• The property `balance` enables us to check the balance of an address.
• The function `transfer(...)` allows us to send Ether expressed in units of Wei to a `payable` address.

Both use cases are shown in the example:

```address payable x = payable(0x123);
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
```

The transfer function will fail if the balance on the current contract is smaller than 10 Wei or if the receiving account rejects the transfer. In case of a failure, the `transfer()` function will revert.

π‘ Note: If `x` in the source code above holds a contract address, its source code, i.e. its function for receiving Ether or its fallback function, will be executed with the call of the `transfer(...)` function. This behavior is an inherent, non-optional feature of EVM. If the execution of these functions depletes the attached gas or fails in some other way, the Ether transfer will be reverted, and the current contract will terminate, raising an exception.

βΉοΈ Info: “The fallback function is executed on a call to the contract if none of the other functions match the given function signature, or if no data was supplied at all and there is no receive Ether function” (docs).

Speaking of currency (Ether) transfer, the `send(...)` function represents the low-level variant of the `transfer(...)` function. If the `send(...)` function execution fails, the current contract will not terminate throwing an exception, but instead, `send(...)` will return a boolean value `false`.

Warning: The `send(...)` function also brings some dangers with it, e.g. the transfer will fail if the call stack depth reached 1024, and the caller can force such an event.

Also, the transfer will fail if the currency recipient runs out of gas. Therefore, good programming patterns for safe Ether transfer include checking the return value of the `send(...)` function or using the `transfer(...)` function, but the best pattern is the one where the recipient withdraws the currency.

When we want to interface with the contracts that are not compliant with the ABI or get direct control over the encoding process, we would use the functions `call(...)`, `delegatecall(...)`, and `staticcall(...)`.

Their input parameter is a single bytes memory and the return results are the success condition (bool type) and the returned data (bytes memory type, same as the input parameter).

The functions `abi.encode(...)`, `abi.encodePacked(...)`, `abi.encodeWithSelector(...)`, and `abi.encodeWithSignature(...)` are available for encoding the structured data:

```bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");
require(success);```

Warning: since `abi.` functions mentioned above are low-level functions, they should be used with caution, i.e. an unknown contract may be malicious, and if we call it, we’re giving it control that might be used to call our contract in return.

In that case, we should prepare for contract state changes with the call return. The regular way of interacting with other contracts is calling a function exposed on a contract `x`‘s object, e.g. `x.f()`.

The amounts of supplied gas and Ether can be adjusted during the function call by supplying the gas and Ether modifiers:

```address(nameReg).call{
gas: 1000000, value: 1 ether
}(abi.encodeWithSignature("register(string)", "MyName"));
```

Of course, we could’ve placed the entire `call(...)` function call in the same line, but I split it into three lines for better readability.

Similar to the `call(...)` function, the `delegatecall(...)` function can also be called, but as mentioned a few articles before, only the code of the given address (contract) will be used, and everything else, such as storage, balance, etc. will be left out.

Let’s remind ourselves, `delegatecall(...)` can only call the library code stored in this other contract. However, it is up to us as users to check if the layout of storage in both contracts is suitable for calling the `delegatecall(...)`.

π‘ Note: Before the EVM version Homestead, only a limited variant of the `delegatecall(...)` function named `callcode(...)` was available, but it didn’t provide access to the original `msg.sender` and `msg.value` values. `callcode(...)` was removed in Solidity v0.5.0.

π‘ Further Note: The EVM version Byzantium introduced the `staticcall(...)` function. It can be used the same as the `call(...)` function, however it will revert if the called function modifies the contract state.

We should have in mind that all three functions, `call(...)`, `delegatecall(...)`, and `staticcall(...)` work on a very low level and should be used only when there’s no other way to achieve the required functionality because the use of these functions violates the type-safety of Solidity.

The `gas` option is available on all three methods, while the `value` option is only available on the call(…) function.

π‘ Note: The best practice is to avoid using hardcoded gas values in our smart contracts, regardless of the access to the state variables.

There are two more noteworthy `address` type members in the context of our story: `code` and `codehash`.

• Member `<address>.code` enables us to query the deployed code for a smart contract, i.e. to get the EVM bytecode in the form of bytes memory, which can be empty.
• Member `<address>.codehash` provides us with the Keccak-256 hash of the deployed source code in the form of bytes32.

We should be aware that `<address>.codehash` is cheaper than calling the function `keccak256(addr.code)`.

As was mentioned a few articles ago, every contract can be converted to the `address` type, so getting the contract’s balance is possible via `address(this).balance`.

## Conclusion

With this article, we made three more very important steps in the direction of getting to know Solidity data types, namely fixed-point numbers, address, and address type members.

What we get by closely knowing Solidity data types being able to select the right data type in a specific situation.

Also, this knowledge gives us the fighting chance to avoid common mistakes and pitfalls during the design and coding phases in creating our smart contracts.

First, we made a polite and gentle introduction to today’s topics.

Second, we explained what fixed point numbers are, made a short comparison with the floating point numbers, and jumped on the next, important point.

Third, we never before got so close with addresses. Any closer, and we’d go postal.

Fourth, we jumped into a detailed discussion about address type members (functions and properties). It got quite technical, but there’s no better way of learning than poppin’ the hood.

## What’s Next?

This tutorial is part of our extended Solidity documentation with videos and more accessible examples and explanations. You can navigate the series here (all links open in a new tab):