Skip to content

Latest commit

 

History

History
72 lines (46 loc) · 3.61 KB

File metadata and controls

72 lines (46 loc) · 3.61 KB
title tags
03. 字节数组和字符串的存储布局
solidity
storage
storage layout
mapping
dynamic array
state variables

WTF Solidity内部标准: 03. 字节数组和字符串的存储布局

《WTF Solidity内部标准》教程将介绍Solidity智能合约中的存储布局,内存布局,以及ABI编码规则,帮助大家理解Solidity的内部规则。

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/AmazingAng/WTF-Solidity-Internals


这一讲,我们将介绍字节数组bytes和字符串string类型的状态变量是如何在合约中存储的。

字节数组和字符串

字节数组和字符串的编码是相同的,存储布局类似于bytes1[](元素为1字节的动态数组),即有一个存放数组长度的槽和一个由哈希决定的数据区。但是对于长度小于32字节的短字节,元素与长度存储在同一个槽中。

我们以BytesStorage合约为例,其中声明了两个状态变量,一个为短字符串"WTF",另一个为长字节365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3

contract BytesStorage {
    string public shortString = "WTF";
    bytes public longBytes = hex"365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3";

    function getHash(bytes memory bb) public pure returns(bytes32){
        return keccak256(bb);
    }
}

短字节

对于短字节/字符串(长度<=31字节),字符串的内容和长度会存到同一个槽中,从而节省gas。字符串的内容从最高阶字节开始存,而字节长度的两倍(len * 2)则会存储在最低阶的字节中。

上面合约中的shortString变量仅占用Slot 0,"WTF"字节长度为3ASCII值为575446,在存储槽中表示为5754460000000000000000000000000000000000000000000000000000000006

长字节

对于长字节/字符串(长度>31字节),存储方式与动态数组相同,只不过存储槽p存储的不是数组长度,而是字符串长度 * 2 + 1。这样,我们可以通过检查最低位是否为0来区分短字节(为0)和长字节(为1)。

上面合约中的longBytes变量的长度为44字节,字符串长度 * 2 + 189,写作十六进制为0x59,保存在Slot 1。接下来前32字节保存在Slot keccak(1),后面的12个字节保存在Slot keccak(1)+1

因此,BytesStorage合约的存储布局为:

Name Slot Value
shortString 0 5754460000000000000000000000000000000000000000000000000000000006
longBytes.length *2 +1 1 0x59
longBytes.first 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 0x365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d
longBytes.second 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7 0x5f5f3e5f3d91602a57fd5bf30000000000000000000000000000000000000000

**注意:**字节/字符串与值变量不同,以左对齐的方式存储(从最高阶开始存),不够32字节的话右边补零

总结

这一讲,我们介绍了字节数组和字符串的存储布局,短字节和长字节有着不同的存储布局,需要注意。