back

Rick · · Updated

Solmate vs Solady — the evolution of gas-optimized Solidity

Dev tooling

Solmate's README answers this comparison itself:

Solmate is no longer actively maintained. Solady has effectively succeeded the project.

That notice was added on 9 July 2025. It is a cleaner answer than any adoption statistic, and it makes the interesting question a different one: if you switch, what do you actually get?

So I measured it. The same ERC-20, the same ERC-721 and the same utility calls, written three times on top of Solmate, Solady and OpenZeppelin, proven to behave identically, then measured under one EVM.

The result reframed the article. Solady is genuinely cheaper, but on the operations most projects care about the gap is 80 to 415 gas — around one percent of an ERC-20 transfer. The large differences are elsewhere: deployment cost, bytecode size, ERC-721 transfers, scope, and licensing.

The maintainer settled it

Solmate's last commit to its default branch landed on 21 July 2025, and it edited the LICENSE file. In the 52 weeks to 8 September 2026 the repository received zero commits. Its only tagged release is v6, from 1 January 2022; the newest npm publish is 6.8.0 from 29 October 2024.

Solady recorded 34 commits over the same period, the most recent on 2 September 2026, and eleven of them are labelled bug fixes.

There is a wrinkle worth knowing before you treat that as a clean win, and I come back to it below: Solady's last tagged release is also a year old.

What the switch actually buys

I built one project that imports all three libraries, implemented the same contracts on top of each, and measured one operation at a time. Setup:

  • solc 0.8.36, optimizer on, 200 runs, EVM target osaka, no via-IR
  • Foundry 1.5.1, on an Apple M3 Pro with 12 logical CPUs
  • solmate 6.8.0, solady at main commit 2afba69b, @openzeppelin/contracts 5.6.1

The discipline is the same one I used for the Foundry vs Hardhat benchmark: report the setup, measure the thing a user actually pays for, and say what the result cannot prove.

Contracts are deployed in setUp() so the storage a measured call touches is clean and cold, every value read inside a gasleft() window is a local or a constant, and each measured call gets its own actors so nothing inherits warm storage from the measurement before it. The token account is warmed with a storage-free call first, so the numbers cover execution rather than the EIP-2929 cold-account premium. They exclude the 21,000-gas transaction base cost and calldata, which are identical across all three.

The generator, harness, raw JSON and a per-file content hash of every measured library file are in the repository under examples/articles/solmate-vs-solady.

ERC-20

Operation Solmate Solady OpenZeppelin Solady vs Solmate
transfer, recipient already holds a balance 13,072 12,925 13,386 −147 (1.1%)
transfer, recipient starts at zero 30,169 30,021 30,481 −148 (0.5%)
transferFrom 18,603 18,188 18,997 −415 (2.2%)
approve, fresh slot 25,044 24,964 25,284 −80 (0.3%)
permit 49,408 49,105 49,979 −303 (0.6%)
_mint to a new account 30,000 29,900 30,285 −100 (0.3%)
balanceOf 2,970 2,977 2,969 +7
Deployment 629,115 463,725 839,481 −165,390 (26.3%)
Deployed bytecode, bytes 2,743 2,154 3,792 −589 (21.5%)

The reason the per-call numbers are so close is that a token transfer is mostly storage. In the cheapest case, two cold SLOADs and two SSTOREs cost 10,000 gas before either library executes a single instruction of its own logic, and the Transfer event costs another 1,756. Assembly can shave the arithmetic and the dispatch around that; it cannot shave the storage.

This is where the widely repeated "300 to 500 gas saved per ERC-20 call" figure comes from, and it is measuring the wrong pair. Against OpenZeppelin, Solady saves 461 gas on a transfer and 809 on a transferFrom. Against Solmate it saves 147 and 415. The figure describes the distance to OpenZeppelin, not the distance to Solmate.

Four horizontal bar charts comparing Solmate, Solady with a constant name, Solady with a stored name, and OpenZeppelin. ERC-20 deployed bytecode: 2,743, 2,154, 2,302 and 3,792 bytes. ERC-20 deployment gas: 629,115, 463,725, 539,539 and 839,481. ERC-20 transfer gas to a recipient that already holds a balance: 13,072, 12,925, 12,925 and 13,386. ERC-721 transferFrom gas sent by an approved spender: 36,304, 33,535 and 36,911, with no stored-name variant.

Deployment cost and code size differ by a quarter. The transfer that users actually pay for differs by about one percent.

Note the third bar in the deployment panels. Roughly 46% of Solady's deployment saving is not codegen at all — it is that the idiomatic Solady token returns its name and symbol as compile-time constants, so deployment writes no metadata storage:

/// Solmate stores `name` and `symbol` in storage and `decimals` as an immutable.
contract SolmateToken is SolmateERC20 {
    constructor(string memory n, string memory s) SolmateERC20(n, s, 18) {}

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}

/// The idiomatic Solady token: `name()` and `symbol()` are compile-time
/// constants, so deployment writes no metadata storage at all.
contract SoladyToken is SoladyERC20 {
    function name() public pure override returns (string memory) {
        return "Benchmark Token";
    }

    function symbol() public pure override returns (string memory) {
        return "BENCH";
    }

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}

That is a design tradeoff, not free money: the same bytecode can no longer be deployed under a different name. I measured a third variant with the metadata back in storage to separate the two effects. It deploys for 539,539 gas — still 14% under Solmate, but a long way from 26%.

ERC-721

The ERC-721 result is the one place where the per-call difference is large enough to plan around.

Operation Solmate Solady OpenZeppelin Solady vs Solmate
transferFrom by an approved spender 36,304 33,535 36,911 −2,769 (7.6%)
_mint, first token to an account 47,491 47,261 47,696 −230 (0.5%)
_mint, second token to an account 30,391 30,161 30,603 −230 (0.8%)
approve 27,221 27,159 27,555 −62 (0.2%)
ownerOf 2,985 2,997 3,026 +12
Deployment 731,689 515,215 848,101 −216,474 (29.6%)
Deployed bytecode, bytes 3,261 2,411 3,842 −850 (26.1%)

Solady's ERC-721 describes itself as having "storage hitchhiking": owner, balance, approval and auxiliary data are packed so a transfer touches fewer slots. That buys 2,769 gas, and it is a storage win rather than an assembly win — which is exactly why it is six to nineteen times the ERC-20 differences.

Math and safe transfers

Operation Solmate Solady OpenZeppelin
safeTransfer of a standard ERC-20 16,612 16,529 16,634
mulWad / mulWadDown / Math.mulDiv 921 872 1,026
divWad / divWadDown 888 821 982
sqrt 1,041 985 1,343

Two things stand out. The fixed-point helpers show the biggest proportional gaps in the whole exercise — Solady's sqrt is 27% cheaper than OpenZeppelin's — but in absolute terms they are worth 49 to 67 gas against Solmate and 154 to 358 against OpenZeppelin, so they only matter in a loop. And safeTransfer is effectively a tie: 105 gas separates OpenZeppelin's SafeERC20 from Solady, because all three now do the same thing, including the extcodesize check that Solmate added in October 2024.

I repeated the whole measurement with the optimizer at 1,000,000 runs, which is what Solmate's own foundry.toml uses. Every runtime figure drops by 100 to 230 gas, every bytecode size grows, deployment gets more expensive, and the ordering does not change anywhere. Raw data for both settings is in the repository.

That is worth holding next to the library numbers. An optimizer flag moved runtime gas by roughly as much as the choice between Solmate and Solady did. The same question one level further down — which compiler pipeline, and which language — is the ground Solidity vs Vyper covers.

What this does not prove

One workload, one machine, one compiler version. It measures the base ERC-20 and ERC-721 implementations and three utility calls, not the rest of what either library contains. Real contracts inherit, override, add hooks and combine libraries, and any of those can move the numbers.

It also measures cost, not correctness. Both libraries are heavy on inline assembly and both tell you so; Solmate's README says its contracts are "not designed with user safety in mind," and Solady's says to "always include your own thorough tests." Finishing a transfer for less gas is not evidence that either one is safer.

The scope difference is real, but not where it is usually placed

The common framing is that Solmate covers core primitives and Solady covers the ERC standards. That is not what is in the repositories.

Solmate ships ERC-20, ERC-721, ERC-1155, ERC-4626, ERC-6909 and WETH. Solady ships the same six plus ERC-20Votes and ERC-2981. On token standards they are nearly level.

The gap is in everything else. Counting distinct contracts, and excluding Solady's auto-generated variants and its one vanity contract:

Solmate Solady
Token implementations 6 8
Authorization 4 4
Account abstraction 0 12
Utilities 10 51
Total 20 75

The accounts directory is the clearest example of divergence: ERC-4337 accounts and factories, EIP-7702 delegation, ERC-6551 token-bound accounts, ERC-7821 batch execution, ERC-1271 signature validation. Solmate has no equivalent to any of it, and given that account abstraction is where a lot of the last three years of Ethereum standards work went, that is the gap most likely to decide the question for a new project.

The utilities gap is similar in character. Solmate has ten: fixed-point math, safe casts, safe transfers, SSTORE2, CREATE3, Merkle proofs, a reentrancy guard, string conversion, signed WAD math and address packing. Solady has the same ground covered plus clone and proxy factories, enumerable sets and maps, a red-black tree, a min-heap, sorting, a JSON parser, Base58 and Base64, calldata compression, P256 and WebAuthn verification, and transient-storage helpers. Fourteen of Solmate's twenty contracts have a same-named counterpart in Solady.

Solady also ships variants of many libraries — globalized versions generated by scripts in prep/, versions using the CLZ opcode, and zkSync-specific forks — which is why its src directory holds 114 files against the 75 counted above. It is worth knowing that when you go looking for a file.

The license is the tradeoff nobody mentions

Solmate is AGPL-3.0. Solady is MIT. Comparisons of the two usually skip this, and it is the difference most likely to matter to a company.

Run this against an installed copy:

find node_modules/solmate/src -name '*.sol' -not -path '*/test/*' -exec head -1 {} \; | sort | uniq -c

In solmate@6.8.0, the version npm install solmate gives you, that returns 16 AGPL-3.0-only files and 4 MIT. The AGPL group includes ERC20.sol, ERC721.sol, ERC1155.sol, ERC4626.sol, SafeTransferLib.sol, FixedPointMathLib.sol and Auth.sol — in other words, the reason most people install it. The repository's root LICENSE file is now a single line pointing at the per-file identifiers, and package.json still declares AGPL-3.0-only.

There is a nice illustration of the maintenance state buried in that. Owned.sol was relicensed to MIT on 21 July 2025, the day before the last commit. There has been no release since, so npm still ships the AGPL version. On main the split is 15 and 5; on npm it is 16 and 4.

All 114 of Solady's Solidity files carry MIT, and its LICENSE.txt is a plain MIT grant. I am not offering a legal opinion on what the AGPL requires of a deployed contract — that is genuinely unsettled and not my field. The point is narrower: these two libraries were never interchangeable on licensing, and the choice deserves a conversation with whoever owns that decision at your company.

What "more used" actually means

The previous version of this article said Solady had 4,767 dependents against Solmate's 1,382 and called the numbers unambiguous. I went back to reproduce them, and the honest answer is that every available usage metric measures something different, and they do not agree on the direction.

Metric Solmate Solady What it actually counts
GitHub dependency graph, repositories 1,418 5,046 repos with the package in an npm manifest
npm downloads, August 2026 29,951 354,357 package fetches, mostly CI
GitHub code search, Solidity files 18,592 5,472 files containing the import path
GitHub stars 4,285 3,367 historical attention

Solmate's npm figure combines solmate (19,859) and the original @rari-capital/solmate (10,092).

The dependency-graph figures match the shape of the old numbers, and they are the ones I would trust least for this question. GitHub's dependency graph supports twenty package ecosystems and none of them is Solidity. It parses package.json; it does not parse git submodules. Most Foundry projects install these libraries with forge install, which is a submodule, so the graph cannot see them at all. It is a census of the npm-installing minority.

Code search inverts the ranking, and it is worse. I sampled 1,000 results for each library and counted distinct repositories: 356 for Solmate, 298 for Solady. The largest contributors were tintinweb/smart-contract-sanctuary-*, which are archives of Etherscan-verified source, and academic corpora such as columbia/SmartInv — 104 of Solady's 1,000 sampled files were in that one repository. The metric mostly measures how many flattened copies of a library exist in public dumps, which is a proxy for historical deployment, not current adoption.

Stars go the other way again, and only tell you that Solmate was famous first.

I could report the metric that supports the conclusion, and the previous version of this article did. The better move is to stop needing it. Solmate's README says it is unmaintained. That is not a proxy for anything.

Audits, and which version you are running

Solmate has one audit report, added with the v6 release on 1 January 2022. The README's claim that "each major release has been audited" is accurate and there has been one major release.

The audited version is not the version you install. SafeTransferLib gained its extcodesize check in October 2024, almost three years after that report, and ERC-6909 was added in September 2023, also after it. This is normal for a live library. It stops being normal when the library also stops receiving fixes.

Solady has five reports, from Ackee Blockchain with RockawayX, shung on the ERC-721, Cantina, a formal proof of cbrt, and a Cantina and Spearbit review added in January 2025. More scrutiny, more recently.

But Solady's release story has the same shape as Solmate's audit story. Its last tag, v0.1.26, is from 25 August 2025. main is 36 commits ahead, eleven of them bug fixes to LibBytes, LibString, Base58, EnumerableSetLib, LazyShuffler, ERC1967BeaconProxy and others. So forge install vectorized/solady gives you an untagged commit with fixes no release contains, and npm install solady gives you a year-old release missing all of them. Neither is the audited tree.

The practical consequence: pin a commit, write it down, and read the diff before you move it. That advice applies to any assembly-heavy library, and it applies more here because the tag you would normally pin to is stale.

Both are one-maintainer libraries

Worth being clear-eyed about, because it is the risk the deprecation notice actually exposes.

Vectorized has 1,478 of Solady's 1,664 commits. transmissions11 has 376 of Solmate's 440. Both projects are one person with a contributor list attached. Migrating from Solmate to Solady does not reduce single-maintainer exposure; it moves to a maintainer who is still committing. That is a real improvement and a narrow one.

Where OpenZeppelin actually sits

The old version of this article framed OpenZeppelin as the safe, slow option. The measured penalty is smaller than that framing implies: 3.6% more gas than Solady on an ERC-20 transfer, 4.4% on a transferFrom, and 105 gas on a safe transfer. The ERC-721 transferFrom is the exception at 10.1%, for the same storage-layout reason Solady beats Solmate there. Deployment is where it is genuinely expensive — 839,481 gas against Solady's 463,725, and 3,792 bytes of runtime code against 2,154.

It also does things the other two deliberately do not. My equivalence suite found one divergence worth naming, and it is a safety check rather than an optimization:

function test_TokensDivergeOnZeroAddressTransfer() public {
    vm.startPrank(owner);

    IToken(tokenOf["solmate"]).transfer(address(0), 1e18);
    IToken(tokenOf["solady"]).transfer(address(0), 1e18);
    IToken(tokenOf["solady-stored-name"]).transfer(address(0), 1e18);
    assertEq(IToken(tokenOf["solmate"]).balanceOf(address(0)), 1e18);
    assertEq(IToken(tokenOf["solady"]).balanceOf(address(0)), 1e18);

    vm.expectRevert();
    IToken(tokenOf["openzeppelin"]).transfer(address(0), 1e18);

    vm.stopPrank();
}

Send tokens to the zero address and OpenZeppelin reverts. Solmate and Solady credit the balance and move on. That is the minimalist bargain stated precisely: the checks you are not paying for are checks that are not running.

OpenZeppelin also releases on a schedule — 5.6.1 in February 2026, 5.7.0 in July 2026 — which means there is always a version number you can pin, cite in an audit, and upgrade deliberately. Even there, check what you are getting: npm's latest tag still resolves to 5.6.1. For a lot of teams that is worth more than 461 gas.

What I would do now

Starting a new gas-sensitive project. Solady, pinned to a specific commit rather than the stale tag, with your own tests around whatever you inherit from it. It is the only one of the three that is both current and cheap.

Sitting on a Solmate codebase. There is no emergency. The contracts still compile, and the audit that was done was done. But nothing is coming: no fixes, no new standards, no response to the next EVM change. Treat it as frozen code you now own, and check whether the AGPL headers in your dependency tree are a problem before someone in legal finds them for you. If you are migrating a component, ERC-721 is where the measured payoff is real.

Not actually gas-bound. On an L2, or for operations that happen rarely, the difference between these libraries is 3 to 4% of a transfer. OpenZeppelin's documentation, release cadence, upgrade tooling and defensive checks are worth more than that. Choosing it is not a failure of ambition.

Solady did succeed Solmate, and Solmate says so itself. What the measurement adds is proportion. The reason to move is that one library is maintained and the other is not, and that the licensing is cleaner and the scope is four times larger. The gas is a rounding error on most transfers and a real 7.6% on NFT transfers.

Solmate's contribution is not diminished by any of this. It established that a minimal, opinionated, gas-conscious alternative to OpenZeppelin could be production-grade, and Solady began, in its own first README, as "a laboratory for cutting edge snippets that may be merged into Solmate." Four years later the laboratory is the library. That is a good outcome for an ecosystem, even if it is an awkward one for anyone who pinned the original.