Let's say I have a string list of parameters
["Example String", "vitalikbuterin", "1000"]
How can I encode this list into a bytes object, and then decode the bytes to get the exact same list?
You could convert string arrays to bytes where each byte is a character and you can use byte 0x00
as a separator.
Here's a contract with the 2 methods you need to pack or unpack a string[] memory
to/from a bytes memory
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;
contract StringsAndBytes {
function packString(string[] memory list) external pure returns (bytes memory){
bytes memory packedArray;
if (list.length == 0) {
return packedArray;
}
packedArray = abi.encodePacked(list[0]);
for (uint i = 1; i < list.length; i++) {
packedArray = abi.encodePacked(packedArray, hex"00", list[i]);
}
return packedArray;
}
function unpackString(bytes memory pack) external pure returns (string[] memory) {
if (pack.length == 0) {
string[] memory emptyArray;
return emptyArray;
}
uint256 elementCount = 1;
for (uint i = 0; i < pack.length; i++) {
if (pack[i] == 0x00) {
elementCount++;
}
}
string[] memory list = new string[](elementCount);
uint256 arrayIndex = 0;
string memory element = "";
for (uint i = 0; i < pack.length; i++) {
if (pack[i] == 0x00) {
list[arrayIndex] = element;
element = "";
arrayIndex++;
continue;
}
element = string(abi.encodePacked(element, pack[i]));
}
list[arrayIndex] = element;
return list;
}
}
Now if I call
packString(["Example String", "vitalikbuterin", "1000"])
I get: 0x4578616d706c6520537472696e6700766974616c696b6275746572696e0031303030
Then i can call
unpackString("0x4578616d706c6520537472696e6700766974616c696b6275746572696e0031303030")
I get ["Example String", "vitalikbuterin", "1000"]
I had never used abi.decode
before in my life. I made this answer, then I thought I'd ask an AI that shall not be named, it gave me a much simpler almost working code (that I fixed) but the resulting bytes end up with a lot of zeroes:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract StringsAndBytesByAI {
function encodeStringList(string[] memory stringList) public pure returns (bytes memory) {
return abi.encode(stringList);
}
function decodeStringList(bytes memory encodedList) public pure returns (string[] memory) {
string[] memory decodedList = abi.decode(encodedList, (string[]));
return decodedList;
}
}
calling
encodeStringList(["Example String", "vitalikbuterin", "1000"])
gives the following result:
0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000e4578616d706c6520537472696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e766974616c696b6275746572696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043130303000000000000000000000000000000000000000000000000000000000
And it can be reversed:
decodeStringList("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000e4578616d706c6520537472696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e766974616c696b6275746572696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043130303000000000000000000000000000000000000000000000000000000000")
Result: ["Example String", "vitalikbuterin", "1000"]
If you need to optimize for storage, use the first one, if you need to optimize for computation, use the second one.
Hello you can use this website to encode https://www.rapidtables.com/convert/number/hex-to-decimal.html
Batching a list into a single bytes object can be done by using the encode_abi() function from Solidity. This function takes a list of elements and returns a bytes object with the data stored in the proper format.
_abi_encode()
from Vyper? It's called abi.encode()
in Solidity.
To batch list into a single bytes object, you can use the "bytearray" function in Python. This function takes a list of values and returns a bytes object.
For example, if you have a list of numbers such as [1,2,3,4], you can create a bytes object using this code:
bytearray([1,2,3,4])
This will return a bytes object containing the values 1,2,3,4.