struct 中 bytes 和 string类型位置计算

本文探讨了在智能合约中,当值长度小于32字节时,bytes和string如何存储以及如何计算其位置。对于长度小于32字节的数据,长度乘以2会存储在高位字节中;若长度超过32字节,则存储位置由length乘以2加1决定,并在相应keccak256哈希位置存储数据。通过示例展示了不同长度值的存储和计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract Test {
    uint256 zero // slot 0
    uint256 one; // slot 1
    uint256 two; // slot 2
    uint256 there;// slot 3
   
    
    struct AAA {
        uint256 a;
        uint256 b;
        bytes c;
    }
    
     mapping(uint256 => AAA[]) public ddd; // slot 4

        constructor() {
        //ddd[2].push(AAA({a: 9, b: 10,c:"string input4"})); //小于32字节的
        ddd[2].push(AAA({a: 9, b: 10,c:"string input4 more than 64 hahaha"}));  

    }        
}

c的位置计算是通过一下:

uint256(keccak256(abi.encodePacked(keccak256(abi.encodePacked(2, 4)))) + 2

后边加的2 是通过index 算来的,a的index=0 c就是2了

c 的位置是:115422248451717562185388182079897522298857624646553443070743177396828943826236 值为:bytes32: ret 0x737472696e6720696e707574340000000000000000000000000000000000001a--1a--16转10进制为26--代表的识length(13)*2 =26 1a之前是数据转化完后就是string input4

但是如果大于32字节,c 的位置是:115422248451717562185388182079897522298857624646553443070743177396828943826236 此时存储的就是length(值为33)*2 +1 =67 返回是 bytes32: ret 0x0000000000000000000000000000000000000000000000000000000000000043 低位43 16转10进制为67,这是具体的字符串value存储的位置为uint256(keccak256(abi.encodePacked(slot))); slot 为c的位置115422248451717562185388182079897522298857624646553443070743177396828943826236

然后计算数据存储的位置48107489538665329287718715171855900440650012581208935513126464494439610548754 取对应位置的值:0x737472696e6720696e70757434206d6f7265207468616e203634206861686168 转string为:string input4 more than 64 hahah

知识补给:

bytes 和 string

bytes 和 string 的编码是相同的。 一般来说,编码与 bytes1[] 类似,即有一个槽用于存放数组本身和一个数据区, 这个数据区是用该槽的位置的 keccak256 哈希值计算的。 然而,对于较短的值(短于32字节),数组元素与长度一起存储在同一个槽中。

特别是:如果数据最多只有 31 字节长, 元素被存储在高阶字节中(左对齐),最低阶字节存储值 length * 2。 对于存储数据长度为 32 或更多字节的字节数,主槽 p 存储 length * 2 + 1, 数据照常存储在 keccak256(p)。这意味着您可以通过检查最低位是否被设置来区分短数组和长数组: 短数组(未设置)和长数组(设置)

//0x737472696e6720696e70757434206d6f7265207468616e203634206861686168

function bytes32ToString(bytes32 _bytes32) external pure returns (string memory) {

bytes memory bytesArray = new bytes(32);

for (uint256 i ; i < 32; i++) {

bytesArray[i] = _bytes32[i];

}

return string(bytesArray);

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值