Put your bytecode on a diet

Health warning: strings are bad for your smart contract's health! You want smaller bytecode? Read on!

Put your bytecode on a diet
Photo by Steve Johnson / Unsplash
Health warning: strings are bad for your smart contract's health!

I like features, and often cram as many as possible into a smart contract. This means that on occasion I do battle with Spurious Dragon.

You may have encountered this end-level boss yourself.

Image

Use Custom Errors

An easy way to squeeze bytes out of your bytecode is to use custom errors rather than require statements. The strings you are using in your require statement are very costly, both in terms of bytecode size and gas cost to execute.

So this:

require(beauty == truth, "Beauty is truth, truth beauty");

Becomes this:

if (beauty != truth) {
  revert BeautyIsTruthTruthBeauty();
}

You'll also need to define the custom error in your code (I abstract mine out into interfaces so they can be shared, but you don't have to).

error BeautyIsTruthTruthBeauty();

Level 2!

The above will have freed you up some bytes. But maybe you still have a problem with Spurious Dragon? Or maybe you want to slim your bytecode down even more and show that draconian arbitrary limit who's the boss!

You can go even more lightweight by not calling revert, but using assembly to log the custom error, passing the selector of the custom error directly.

First add this internal method to your code:

function _revert(bytes4 boSelecta) internal pure {
  assembly {
    mstore(0x00, boSelecta)
    revert(0x00, 0x04)
  }
}

Then, instead of calling revert, you do this:

if (beauty != truth) {
  _revert(BeautyIsTruthTruthBeauty.selector);
}

Boss Defeated!

If you have swapped your require statements for assembly based custom errors you will have removed a significant number of bytes from your bytecode. If you are pleased with the results, why not share them below (or on twitter https://x.com/0mnus).

Need more bytecode saving ideas? I've got 'em, just let me know.