如何将msg.sender强制转换为uint32?

huangapple go评论46阅读模式
英文:

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)中直接在addressuint<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`

huangapple
  • 本文由 发表于 2023年5月21日 03:37:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297036.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定