Again, the important thing to remember here is that casting from a larger type to a smaller type means that you are left with the least significant part of the original value.

For example, given the 64-bit value:

```
x == b63, b62, b61, ..., b2, b1, b0
```

If we cast it to a 32-bit value:

```
y = uint32(x)
```

Then we get the 32-bit value:

```
y == b31, b30, b29, ..., b2, b1, b0
```

Now, in order to compare between them, we first need to expand `y`

to the size of `x`

.

Of course, we can't change the actual value of `y`

, so we only expand it with leading zeros:

```
y == 0, 0, 0, ..., b31, b30, b29, ..., b2, b1, b0
```

Then we finally compare between them:

```
x == b63, b62, b61, ..., b34, b33, b32, b31, b30, b29, ..., b2, b1, b0
y == 0 , 0 , 0 , ..., 0 , 0 , 0 , b31, b30, b29, ..., b2, b1, b0
```

As you can see, they are equal **if and only if** bits 63-32 are all zeros.

If you still find it hard to understand, let's simulate the whole thing with a pair of values in base 10:

- Let
`x = Decimal8(ABCDEFGH)`

- Let
`y = Decimal4(x) = EFGH`

- Compare:
`x == ABCDEFGH`

`y == 0000EFGH`

As you can see, `x == y`

if and only if `ABCD == 0000`

Now it should hopefully be easier for you to see why:

`uint32(uint64(n)) == uint16(uint64(n))`

requires that bits 16-31 are**all**set to zero`uint32(uint64(n)) != uint64(n)`

requires that bits 32-63 are**not all**set to zero

As for the construction of the value of `_gateKey`

as a hexadecimal string - note that such strings:

- Are used for representing numerical values in base 16 (aka "hexadecimal")
- Consist of characters from the set [0 thru 9] and from the set [A thru F]
- Are case-insensitive, hence the set [A thru F] is synonymous [a thru f]
- Typically start with the prefix "0x" (though it is application-dependent)

Each character represents a unique sequence of 4 bits, denoting a unique value in base 2:

```
+-----------+--------------+---------------+
| Character | Bit Sequence | Decimal Value |
+-----------+--------------+---------------+
| 0 | 0000 | 0 |
| 1 | 0001 | 1 |
| 2 | 0010 | 2 |
| 3 | 0011 | 3 |
| 4 | 0100 | 4 |
| 5 | 0101 | 5 |
| 6 | 0110 | 6 |
| 7 | 0111 | 7 |
| 8 | 1000 | 8 |
| 9 | 1001 | 9 |
| A | 1010 | 10 |
| B | 1011 | 11 |
| C | 1100 | 12 |
| D | 1101 | 13 |
| E | 1110 | 14 |
| F | 1111 | 15 |
+-----------+--------------+---------------+
```

For example, the string `"0x14E5"`

represents the bit-sequence `0001 | 0100 | 1110 | 0101`

.

Let's assume that the last 4 characters (least 16 bits) in the wallet address are `A57C`

.

Hence the value of `_gateKey`

can be constructed as:

```
const _gateKey = "0x"
+ "00" // the bit-sequence 0000|0000 is placed between bit 63 and bit 56
+ "00" // the bit-sequence 0000|0000 is placed between bit 55 and bit 48
+ "00" // the bit-sequence 0000|0000 is placed between bit 47 and bit 40
+ "01" // the bit-sequence 0000|0001 is placed between bit 39 and bit 32
+ "00" // the bit-sequence 0000|0000 is placed between bit 31 and bit 24
+ "00" // the bit-sequence 0000|0000 is placed between bit 23 and bit 16
+ "A5" // the bit-sequence 1010|0101 is placed between bit 15 and bit 8
+ "7C" // the bit-sequence 0111|1100 is placed between bit 7 and bit 0
```