CRYPTO NEWS

Copying strings and bytes from memory to storage via storage references

What’s the proper way to copy a string (or bytes) from memory to storage? When copied directly into a state variable lvalue (or into a mapping), there’s no problem, but when assigning a string memory rvalue into a string storage lvalue, there’s a compiler error.

The Solidity documentation suggests that it ought to be possible to assign a memory reference to a storage reference and that the behavior is that the pointed-to value in memory is copied into the pointed-to location in storage. Why is it different when the lvalue is a reference instead of a state variable or mapping?

I suppose I could code this myself in Yul, but I’d prefer to avoid re-implementing the rules regarding the handling of short string/bytes in storage.

pragma solidity ^0.8.15;  contract Works {   string public thing;    function setThing(string memory newValue) public {     thing = newValue;   } }  contract AlsoWorks {   mapping(bytes32 => string) public things;    function setThing(bytes32 key, string memory newValue) public {     things[key] = newValue;   } }  contract Fails {   string public thing;    function setThing(string memory newValue) public {     string storage thingLocal = thing;     thingLocal = newValue;   } } 

What I’m actually trying to do here is to store a string at a slot that is impossible to accidentally clobber so that it is preserved across contract upgrades. A more concrete example:

pragma solidity ^0.8.15;  abstract contract MagicSlot {   uint256 internal constant _MAGIC_SLOT = 0xcafef00dcafef00dcafef00dcafef00dcafef00dcafef00dcafef00dcafef00d;    function _magic() internal pure returns (string storage result) {     assembly ("memory-safe") {       result.slot := _MAGIC_SLOT     }   }    function magic() external view returns (string memory) {     return _magic();   } }  contract Fails is MagicSlot {   function setMagic(string memory newValue) public {     // TypeError: Expression has to be an lvalue.     // TypeError: Type string memory is not implicitly convertible to expected type string storage pointer.     _magic() = newValue;   } }  contract AlsoFails is MagicSlot {   function setMagic(string memory newValue) public {     string storage magicRef = _magic();     // TypeError: Type string memory is not implicitly convertible to expected type string storage pointer.     magicRef = newValue;   } } 

Copying strings and bytes from memory to storage via storage references

Shopping cart
There are no products in the cart!
Continue shopping
0