英文:
How does this type casting msg.sender to uint32 work?
问题
In the provided code, casting msg.sender
to a uint32
variable helps determine if the last 8 hexadecimal characters are zero. This is because each hexadecimal character represents 4 bits, and a uint32
variable is 32 bits long.
When you cast msg.sender
to uint32
, you effectively convert the address to a 32-bit integer. This integer will contain the hexadecimal representation of the address in its least significant bits (from right to left). If the last 8 hexadecimal characters are zero, it means the least significant 32 bits of the address are all zeros.
So, by checking if uint32(msg.sender) == 0
, you are verifying if the least significant 32 bits of the address (the last 8 hexadecimal characters) are all zeros, which is a condition for being a winner in this context.
英文:
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?
答案1
得分: 2
msg.sender
是一个类型为 address
的全局变量,长度为160位(等于20字节)。
uint32
是一个32位(等于4字节)的无符号整数类型。
每个字节可以表示为2个十六进制字符。例如,由全为二进制1的8个位组成的字节(11111111
)表示为 0xff
。
现在,32位等于4字节,也等于8个十六进制字符。这就是为什么代码注释中提到了8个十六进制字符的原因。
当进行从较大类型到较小类型的类型转换时,会移除高位的位。
虽然在之前的Solidity版本(直到v0.7.6)中直接在address
和uint<N>
之间进行转换是可用的,但在当前版本(0.8.x)中不再支持,您需要采取一些变通方法来将address
转换为uint32
,我的示例展示了更直接的数字之间的转换:
pragma solidity ^0.8;
contract MyContract {
function foo() external pure returns (uint8) {
uint16 larger = 512; // 二进制 00000011 00000000
uint8 smaller = uint8(larger); // 二进制 00000000
return smaller;
}
}
文档链接:https://docs.soliditylang.org/en/v0.8.20/types.html#explicit-conversions
根据您的示例,uint32(msg.sender) == 0
当最后32位(等于8个十六进制字符)都为零时为真。
例如,地址0xabcdabcdabcdabcdabcdabcdabcdabcd00000000
(以8个零十六进制字符结尾)的十六进制表示也可以表示为以下形式(以32个零位结尾)。
10101011 11001101 10101011 11001101 // 十六进制 `abcdabcd`
10101011 11001101 10101011 11001101 // 十六进制 `abcdabcd`
10101011 11001101 10101011 11001101 // 十六进制 `abcdabcd`
10101011 11001101 10101011 11001101 // 十六进制 `abcdabcd`
00000000 00000000 00000000 00000000 // 十六进制 `00000000`
英文:
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`
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论