Solidity Assembly、mstore 函数和一个字的宽度(以字节为单位)

use*_*646 3 ethereum solidity smartcontracts evm

我正在学习 Solidity Assembly,但我对某些事情感到困惑。我正在查看这个名为 Seriality 的库。具体来说,这个函数:https : //github.com/pouladzade/Seriality/blob/master/src/TypesToBytes.sol#L21

function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
    assembly {
        mstore(add(_output, _offst), _input)
        mstore(add(add(_output, _offst),32), add(_input,32))
    }
}
Run Code Online (Sandbox Code Playgroud)

该函数 bytes32ToBytes 接受一个 bytes32 变量并将其存储在动态大小的字节数组中,从传入的偏移量开始。

让我困惑的是它使用了 mstore 函数两次。但是mstore函数存储了一个词,是32个字节,对吧?既然输入是 32 个字节,那么为什么它会被调用两次呢?不会调用它两次存储 2 个字,即 64 个字节?

谢谢!

Ada*_*nis 5

Solidity 数组的存储方式是将数组的大小写入第一个存储槽,然后将数据写入后续槽。

知道mstore有如下参数:mstore(START_LOCATION, ITEM_TO_STORE),第一个mstore语句写成如下:

mstore(add(_output, _offst), _input)
Run Code Online (Sandbox Code Playgroud)

由于数组的第一个槽指向数组的大小,因此该语句是设置 的大小_output。通过将其替换为mstore(add(_output, _offst), 32)(因为大小_input是静态的),您应该能够获得相同的结果。

第二个语句 ( mstore(add(add(_output, _offst),32), add(_input,32))) 是写入数据本身的语句。在这里,我们将两个指针的位置移动了 32 个字节(因为两个数组的前 32 个字节都指向大小)并将 的值存储_input到存储数据的位置_output

机会是,_output已经将调用此方法(这样的长度就已经被设置)之前进行初始化,因此它通常是不必要的。但是,它不痛。请注意,做出此假设的类似实现如下所示:

function test() public pure returns (bytes) {
    bytes32 i = "some message";
    bytes memory o = new bytes(32); // Initializing this way sets the length to the location "o" points to. This replaces mstore(add(_output, _offst), _input).
    bytes32ToBytes(0, i, o);
    
    return o;
}

function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
    assembly {
        mstore(add(add(_output, _offst),32), add(_input,32))
    }
}
Run Code Online (Sandbox Code Playgroud)