职能如下:
function encodeAmount(
uint256 amount,
bytes memory data
) public pure returns(bytes memory){
bytes memory amountToEncode = abi.encode(amount);
assembly {
mstore(add(add(data, 32), 68), mload(add(amountToEncode, 32)))
}
return data;
}数额: 1000000
数据: 0xe5b07cdb0000000000000000000000003416cf6c708da44db2624d63ea0aaef7113527c60000000000000000000000000000000000000000000000000000000000000001
fn应该更改数据中的最后32字节,但函数返回的数据不变。那么,如何获得实际更改的数据呢?
发布于 2022-06-04 09:02:35
fn应该更改数据中的最后32字节,但函数返回的数据不变。那么,如何获得实际更改的数据呢?
您的代码有一个depper问题。所提供的数据似乎包括:
总长度为68个字节。
现在在这条线上:
mstore(add(data,32),68),mload(add(amountToEncode,32)
您可以使用add(data, 32)有效地跳过length字段,但是在不更改length字段或更新空闲内存指针的情况下,在提供的数据之后写入数量。此外,没有必要这样做:
bytes memory amountToEncode = abi.encode(amount);由于总量已经是一个32字节值(uint256)和abi.encoding,所以它只生成一个具有相同值的32字节数组。您还应该确保数据是按照您预期的方式格式化的,即68字节长。如果您正在寻找一种更通用的方法,能够处理可变长度的字节数组,请告诉我。
由于不清楚要在向现有的数据添加数据或覆盖最后32个字节之间到底要做什么,所以在这两种情况下都需要这样做:
function encodeAmount(uint256 amount, bytes memory data) public pure returns(bytes memory) {
require(data.length == 68, "Expected 68 bytes of data");
assembly {
// No need to abi encode amount. It's already a 32 bytes values (uint256).
// Just write it directly after the existing data
mstore(add(add(data, 32), 68), amount)
// Increase the length of the byte array by 32 to account for the added data
mstore(data, add(mload(data), 32))
// Set the free memory pointer to data + 32 + data.length to ensure that
// subsequent allocations do not overwrite what we just added.
mstore(0x40, add(data, add(mload(data), 32)))
}
return data;
}产生0xe5b07cdb0000000000000000000000003416cf6c708da44db2624d63ea0aaef7113527c6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240的
编辑:如果data不是上一次内存分配的结果,我想这个版本有一个缺陷。mstore(0x40, add(data, add(mload(data), 32)))可以取回空闲内存指针,并使内存处于不一致的状态。
此示例说明了该缺陷:
contract Test {
struct Wrapper {
uint256 value;
}
function edgeCase(uint256 amount, bytes memory data) public pure returns (bytes memory, Wrapper memory walue) {
// Assuming data starts at offset 0 :
// data : [0 : 32 + 68] = 100 bytes
// Free memory starts at 100
// wrapper is 32 bytes long allocated at the free memory pointer (100)
// Free memory now starts at 132
Wrapper memory wrapper;
wrapper.value = 0;
// This will take the free memory pointer back to :
// data (0) + 32 (length) + data.length (68) + 32 (amount) = 132
// leaving wrapper in an inconsistent state as it is
// it overwritten by the byte array returned by encodeAmount.
// Both wrapper and the encoded byte array use the same memory space.
// With more than 32 bytes allocated between data and the call
// the free memory pointer will be decremented.
return (encodeAmount(amount, data), wrapper);
}
function encodeAmount(uint256 amount, bytes memory data) public pure returns(bytes memory) {
require(data.length == 68, "Expected 68 bytes of data");
assembly {
// No need to abi encode amount. It's already a 32 bytes values (uint256).
// Just write it directly after the existing data
mstore(add(add(data, 32), 68), amount)
// Increase the length of the byte array by 32 to account for the added data
mstore(data, add(mload(data), 32))
// Set the free memory pointer to data + 32 + data.length to ensure that
// subsequent allocations do not overwrite what we just added.
mstore(0x40, add(data, add(mload(data), 32)))
}
return data;
}
}因此,最好使用下面的版本来创建一个新的字节数组,并确保以前分配的数据的内存一致性。
function encodeAmount(uint256 amount, bytes memory data) public pure returns(bytes memory encoded) {
require(data.length == 68, "Expected 68 bytes of data");
assembly {
// Take a free memory space for the new array
encoded := mload(0x40)
// Set the size of the new array
mstore(encoded, add(mload(data), 32))
// Set the content of the new array by blocks of 32 bytes
for {let i:= 0} lt(i, mload(data)) {i := add(i, 32)} {
mstore(add(add(encoded, 32), i), mload(add(add(data, 32), i)))
}
// No need to abi encode amount. It's already a 32 bytes values (uint256).
// Just write it directly after the existing data
mstore(add(add(encoded, 32), 68), amount)
// Update the free memory pointer
mstore(0x40, add(encoded, add(mload(encoded), 32)))
}
return encoded;
}的最后32个字节
function overwriteAmount(uint256 amount, bytes memory data) public pure returns(bytes memory) {
require(data.length == 68, "Expected 68 bytes of data");
assembly {
// No need to abi encode amount. It's already a 32 bytes values (uint256).
// Just write it directly over the last 32 bytes of data
mstore(add(add(data, 32), 36), amount)
}
return data;
}在这种情况下,不需要更新长度或空闲内存指针,因为我们没有将任何内容更改为内存布局,只更改已经分配的内存空间的内存内容。
产生0xe5b07cdb0000000000000000000000003416cf6c708da44db2624d63ea0aaef7113527c600000000000000000000000000000000000000000000000000000000000f4240的
我希望这能回答你的问题。
https://ethereum.stackexchange.com/questions/129536
复制相似问题