You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity中ENS解析器bytes转address的div(exp(256,12))作用解析

Solidity bytes memory转address的汇编逻辑差异说明

首先明确Solidity bytes memory 类型的内存布局规则:

  • 内存中bytes的起始位置开始,前32字节存储该bytes的实际长度
  • 从起始位置偏移32字节的位置开始,才是bytes存储的真实内容
  • EVM的mload(op)操作会从传入的内存地址op开始,连续读取32字节的数据,返回一个uint256类型的值

原有实现的问题

你之前使用的转换代码存在偏移计算错误:

function bytesToAddress(bytes memory byte) public pure returns (address addr) {
    assembly {
         addr := mload(add(byte, 20))
   }
}

add(byte,20)定位到的是bytes起始位置后20字节的内存点,这个位置还处于存储长度的前32字节区间内,mload读取的32字节会包含长度字段的后12字节+真实内容的前20字节,读出来的值和实际地址完全不匹配,属于错误实现。

ENS公共解析器实现的逻辑拆解

ENS的实现首先通过require(b.length == 20)做了前置校验,保证输入的bytes长度刚好和地址长度(20字节)一致,避免长度异常导致的错误转换,内联汇编部分逐段逻辑如下:

assembly {
    a := div(mload(add(b, 32)), exp(256, 12))
}
  1. add(b,32):跳过bytes开头32字节的长度字段,定位到真实内容的起始内存地址
  2. mload(add(b,32)):从内容起始位读取连续32字节。因为输入的bytes只有20字节长,这32字节里前20字节是我们需要的真实地址值,后12字节是该内存段后面的残留脏数据(不属于当前bytes变量的内容),直接把这个值转成地址会把脏数据也带进去,得到错误结果。
  3. div(..., exp(256,12)):exp(256,12)等价于2^(8*12) = 2^96,无符号整数除以2^96的效果等同于把数值逻辑右移96位,刚好把后面12字节的脏数据全部移出,剩下的高20位就是正确的地址值,最终赋值给address payable类型的返回值。

补充:新版本Solidity(0.5+)已经可以不用汇编直接做类型转换,写法为address(uint160(bytes20(b))),编译器会自动处理内存偏移和截断逻辑,安全性更高。

内容的提问来源于stack exchange,提问作者苍苍张

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:48:24