#100DaysOfSolidity Understanding Bitwise Operators in Solidity

#100DaysOfSolidity Series 044 “Bitwise Operators” : Unlocking the Power of Binary Manipulation 🛠️

Solidity Academy
6 min readJul 20, 2023

👋 Welcome to another exciting article in our Solidity series! In this post, we’ll delve into the fascinating world of “Bitwise Operators” in the Solidity language. These operators are incredibly powerful tools that allow you to manipulate individual bits of binary data at a low level.

#100DaysOfSolidity Series 044 “Bitwise Operators” : Unlocking the Power of Binary Manipulation 🛠️

By mastering bitwise operators, you’ll gain a deeper understanding of Solidity and be able to write more efficient and optimized code. So let’s dive in and unlock the potential of bitwise operators in Solidity! 💪

## What are Bitwise Operators? 🧐

Bitwise operators are operators that perform operations on individual bits of binary data. They enable you to manipulate and extract specific bits, set or clear bits, and perform logical operations at the bit level. Solidity provides a set of bitwise operators that empower developers to work with binary data in a more granular way.

Solidity supports the following bitwise operators:

- Bitwise AND (`&`) ✖️
- Bitwise OR (`|`) ➕
- Bitwise XOR (`^`) ➖
- Bitwise NOT (`~`) ⌛
- Bitwise Left Shift (`<<`) ⬅️
- Bitwise Right Shift (`>>`) ➡️

In the sections that follow, we’ll explore each of these operators in detail, providing you with clear explanations and code samples to illustrate their usage. Let’s get started! 🚀

## Bitwise AND (`&`) ✖️

The bitwise AND operator (`&`) compares the corresponding bits of two operands and returns a new value where each bit is set to `1` if both bits are `1`, and `0` otherwise. Let’s take a look at an example:

```solidity
function and(uint x, uint y) external pure returns (uint) {
return x & y;
}
```

In this example, the `and` function takes two unsigned integer parameters, `x` and `y`, and returns the result of performing a bitwise AND operation on them. For instance, if `x` is `14` (binary `1110`) and `y` is `11` (binary `1011`), the result of `x & y` would be `10` (binary `1010`). 🧮

## Bitwise OR (`|`) ➕

The bitwise OR operator (`|`) compares the corresponding bits of two operands and returns a new value where each bit is set to `1` if at least one of the bits is `1`, and `0` otherwise. Here’s an example:

```solidity
function or(uint x, uint y) external pure returns (uint) {
return x | y;
}
```

In this example, the `or` function takes two unsigned integer parameters, `x` and `y`, and returns the result of performing a bitwise OR operation on them. For example, if `x` is `12` (binary `1100`) and `y` is `9` (binary `1001`), the result of `x | y` would be `13` (binary `1101`). 🌓

## Bitwise XOR (`^`) ➖

The bitwise XOR operator (`^`) compares the corresponding bits of two operands and returns a new value where each bit is set to `1` if the bits are different, and `0` if the bits are the same. Let’s see an example:

```solidity
function xor(uint x, uint y) external pure returns (uint) {
return x ^ y;
}
```

In this example, the `xor` function takes two unsigned integer parameters, `x` and `y`, and returns the result of performing a bitwise XOR operation on them. For instance, if `x` is `12` (binary `1100`) and `y` is `5` (binary `0101`), the result of `x ^ y` would be `9` (binary `1001`). 🔀

## Bitwise NOT (`~`) ⌛

The bitwise NOT operator (`~`) is a unary operator that negates each bit of its operand. It returns a new value where each `0` is replaced by `1`, and each `1` is replaced by `0`. Here’s an example:

```solidity
function not(uint8 x) external pure returns (uint8) {
return ~x;
}
```

In this example, the `not` function takes an unsigned 8-bit integer parameter `x` and returns the result of performing a bitwise NOT operation on it. For example, if `x` is `12` (binary `00001100`), the result of `~x` would be `243` (binary `11110011`). 🔄

## Bitwise Left Shift (`<<`) ⬅️

The bitwise left shift operator (`<<`) shifts the bits of its left-hand operand to the left by a specified number of positions. It effectively multiplies the operand by `2` raised to the power of the shift amount. Let’s take a look at an example:

```solidity
function shiftLeft(uint x, uint bits) external pure returns (uint) {
return x << bits;
}
```

In this example, the `shiftLeft` function takes an unsigned integer `x` and a `bits` parameter, which represents the number of positions to shift the bits. The function returns the result of shifting the bits of `x` to the left by `bits` positions. For instance, if `x` is `1` and `bits` is `3`, the result of `x << bits` would be `8`. ⬅️

## Bitwise Right Shift (`>>`) ➡️

The bitwise right shift operator (`>>`) shifts the bits of its left-hand operand to the right by a specified number of positions. It effectively divides the operand by `2` raised to the power of the shift amount. Here’s an example:

```solidity
function shiftRight(uint x, uint bits) external pure returns (uint) {
return x >> bits;
}
```

In this example, the `shiftRight` function takes an unsigned integer `x` and a `bits` parameter, which represents the number of positions to shift the bits. The function returns the result of shifting the bits of `x` to the right by `bits` positions. For example, if `x` is `8` and `bits` is `2`, the result of `x >> bits` would be `2`. ➡️

## Extracting Last N Bits 📊

Solidity provides two methods to extract the last `N` bits from a given number. Let’s explore both of them.

### Method 1: Using a Bitwise AND Operator (`&`) ✖️

```solidity
function getLastNBits(uint x, uint n) external pure returns (uint) {
uint mask = (1 << n) — 1;
return x & mask;
}
```

In this example, the `getLastNBits` function takes an unsigned integer `x` and an `n` parameter, which represents the number of bits to extract. The function returns the result of applying a bitwise AND operation between `x` and a mask that consists of `n` number of `1` bits. This effectively extracts the last `N` bits from `x`. 📊

### Method 2: Using the Modulo Operator (`%`) 🔄

```solidity
function getLastNBitsUsingMod(uint x, uint n) external pure returns (uint) {
return x % (1 << n);
}
```

In this example, the `getLastNBitsUsingMod` function takes an unsigned integer `x` and an `n` parameter, which represents the number of bits to extract. The function returns the result of applying the modulo operator (`%`) between `x` and `2` raised to the power of `n`. This effectively extracts the last `N` bits from `x`. 📊

## Finding the Most Significant Bit 🌟

The most significant bit (MSB) is the leftmost bit in a binary representation. Solidity provides two methods to find the position of the most significant bit in a given number.

### Method 1: Binary Search 🔎

function mostSignificantBit(uint x) external pure returns (uint) {
uint i = 0;
while ((x >>= 1) > 0) {
++i;
}
return i;
}

In this example, the `mostSignificantBit` function takes an unsigned integer `x` and performs a binary search to find the position of the most significant bit. It repeatedly shifts `x` to the right by `1` position until `x` becomes `0`, counting the number of shifts (`i`) along the way. The final value of `i` represents the position of the most significant bit. 🔍

### Method 2: Assembly Implementation ⚙️

function mostSignificantBit(uint x) external pure returns (uint msb) {
assembly {
let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
x := shr(f, x)
msb := or(msb, f)
}
// … (similar assembly code for other bit positions)
}

In this example, the `mostSignificantBit` function takes an unsigned integer `x` and uses assembly code to find the position of the most significant bit. It employs a series of bitwise operations and conditional checks to determine the position of the most significant bit. ⚙️

## Conclusion 🎉

Congratulations on gaining a solid understanding of bitwise operators in Solidity! By mastering these operators, you can unlock the power of binary manipulation and write more efficient and optimized code. We explored the bitwise AND, OR, XOR, NOT, left shift, and right shift operators, along with techniques to extract the last `N` bits and find the position of the most significant bit.

So go ahead, harness the potential of bitwise operators in Solidity, and elevate your blockchain development skills to new heights! Happy coding! 💻🚀

🔗 Additional Resources:

--

--

Solidity Academy

Learn smart contract development and blockchain integration in depth. https://heylink.me/solidity/ SEND US Your Products to Review! solidity101@gmail.com