// condition is boolean
// str is a string
require(condition, str)
The string str is split into 32-byte sized chunks and then stored in
memory using mstore, then the memory offsets are provided to
revert(offset, length). For chunks shorter than 32 bytes, and for low
--optimize-runs value (usually even the default value of 200), instead
of push32 val, where val is the 32 byte hexadecimal representation
of the string with 0 padding on the least significant bits, the
solidity compiler replaces it by shl(value, short-value)). Where short-value does not have any 0 padding. This
saves the total bytes in the deploy code and therefore saves deploy time
cost, at the expense of extra 6 gas during runtime. This means that
shorter revert strings saves deploy time costs of the contract. Note
that this kind of saving is not relevant for high values of
--optimize-runs as push32 value will not be replaced by a shl(..., ...) equivalent by the Solidity compiler.
Going back, each 32 byte chunk of the string requires an extra mstore.
That is, additional cost for mstore, memory expansion costs, as well
as stack operations. Note that, this runtime cost is only relevant when
the revert condition is met.
Overall, shorter revert strings can save deploy time as well as runtime
costs.
Note that if your contracts already allow using at least Solidity
0.8.4, then consider using Custom
errors. This is
more gas efficient, while allowing the developer to describe the errors
in detail using
NatSpec.
A disadvantage to this approach is that, some tooling may not have
proper support for this, as well as block explorers like Etherscan.
Examples
Here is a non-exhaustive list of lengthy revert strings that could be
shortened:
Handle
hrkrshnn
Vulnerability details
Consider having short revert strings
Consider the following require statement:
The string
str
is split into 32-byte sized chunks and then stored in memory usingmstore
, then the memory offsets are provided torevert(offset, length)
. For chunks shorter than 32 bytes, and for low--optimize-runs
value (usually even the default value of 200), instead ofpush32 val
, whereval
is the 32 byte hexadecimal representation of the string with0
padding on the least significant bits, the solidity compiler replaces it byshl(value, short-value))
. Whereshort-value
does not have any0
padding. This saves the total bytes in the deploy code and therefore saves deploy time cost, at the expense of extra6
gas during runtime. This means that shorter revert strings saves deploy time costs of the contract. Note that this kind of saving is not relevant for high values of--optimize-runs
aspush32 value
will not be replaced by ashl(..., ...)
equivalent by the Solidity compiler.Going back, each 32 byte chunk of the string requires an extra
mstore
. That is, additional cost formstore
, memory expansion costs, as well as stack operations. Note that, this runtime cost is only relevant when the revert condition is met.Overall, shorter revert strings can save deploy time as well as runtime costs.
Note that if your contracts already allow using at least Solidity
0.8.4
, then consider using Custom errors. This is more gas efficient, while allowing the developer to describe the errors in detail using NatSpec. A disadvantage to this approach is that, some tooling may not have proper support for this, as well as block explorers like Etherscan.Examples
Here is a non-exhaustive list of lengthy revert strings that could be shortened: