For example, in the code below, would it be cheaper to store the string
in a mapping
? Or to convert it to bytes32
and store it as bytes32
then convert it back to a string
whenever I call it with JavaScript?
mapping(string => bool) _tokenExists;
function test(string memory _str) public {
_tokenExists[_str] = true;
}
Or
mapping(bytes32 => bool) _tokenExists;
function test(string memory _str) public {
_tokenExists[abi.encodePacked(_str)] = true;
}
Which one of these would be cheaper & better to use and why?
PS: Is there a way I can find out on my own for the future which would be cheaper by doing my own gas estimates?
Best Answer
First of all,
abi.encodePacked(_str)
will convert thestring
_str
to its UTF-8bytes
representation, and not tobytes32
.bytes
is a dynamically-sized byte array, as isstring
. Since Solidity 0.8.5 it’s possible to castbytes
intobytes32
, but you need to pay attention because anything beyond 32 bytes will be chopped off.So if your
string
’s UTF-8bytes
representation is 32 bytes or shorter, you can place it in abytes32
viabytes32(abi.encodePacked(_str))
, whereas if your string is longer than 32 bytes, you can compress it into abytes32
viakeccak256(abi.encodePacked(_str))
.From the Solidity docs:
p
above is the “slot position” for the mapping variable (your_tokenExists
), so within a contract it is constant. For this example, suppose thatp = 0
. So we have:k
bytes32
keccak256( k . 0 )
bytes
orstring
keccak256( keccak256(abi.encodePacked(k)) . 0 )
So for
mapping
s withbytes
orstring
key-type, accessing amapping
value invokes an extrakeccak256
. But invokingkeccak256
is cheap enough to not let it influence your design decisions. Rather you should usestring
orbytes32
depending on what is semantically more suitable for your contract.A simple way to test the theory above “on your own, for the future” is by loading in Remix IDE a test-contract, deploying it to the
JavaScript VM
Environment
, and invoking the different functions with the same input strings, trying both short and long strings, and comparing the different functions’execution cost
, e.g.: