I ran into this example while working through "ethereumbook" on github. In the following code, how does casting the msg.sender address to a uint32 variable determine if the last 8 hexadecimal characters are zero?
contract HashForEther {
function withdrawWinnings() {
// Winner if the last 8 hex characters of the address are 0
require(uint32(msg.sender) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
}
I don't have a great understanding of how hex works, which probably isn't helping me but I don't see how changing msg.sender to a uint32 gives insight on only the last four characters. Is it because 4*8=32 and uint32 takes the value from smallest denomination to highest?
msg.sender
is a global variable of type address
, which has length of 160 bits (== 20 bytes).
uint32
is an unsigned integer type of size 32 bits (== 4 bytes).
Each byte can be represented as 2 hexadecimal characters. For example a byte consisting of all 8 binary ones (11111111
) is represented as 0xff
.
Now, 32 bits, that's 4 bytes, and also 8 hex characters. So that's why the code comment mentiones 8 hex characters.
When you're performing a type conversion into smaller type, it removes the higher-positioned bits.
While direct conversion between address
and uint<N>
was available in previous Solidity versions (until v0.7.6), it is not available in the current version (0.8.x) and you need to do some workarounds to convert address
into uint32
, my example shows a more straightforward conversion just between numbers:
pragma solidity ^0.8;
contract MyContract {
function foo() external pure returns (uint8) {
uint16 larger = 512; // binary 00000011 00000000
uint8 smaller = uint8(larger); // binary 00000000
return smaller;
}
}
Docs: https://docs.soliditylang.org/en/v0.8.20/types.html#explicit-conversions
Given your example, uint32(msg.sender) == 0
is true when the last 32 bits (== 8 hex characters) are zero.
E.g. the hex representation of address 0xabcdabcdabcdabcdabcdabcdabcdabcd00000000
(ending with 8 zero hex characters) can be also represented as the following (ending with 32 zero bits).
10101011 11001101 10101011 11001101 // hex `abcdabcd`
10101011 11001101 10101011 11001101 // hex `abcdabcd`
10101011 11001101 10101011 11001101 // hex `abcdabcd`
10101011 11001101 10101011 11001101 // hex `abcdabcd`
00000000 00000000 00000000 00000000 // hex `00000000`