How a bad standard held back crypto payments for a decade

Being first has great costs. If you're in a jungle, you're the one macheting down the vines and shrubs. If you're a cyclist in a race, you're the one pushing the air forward, whilst the cyclists behind can relax in your draft. And if you're developing a first of its kind product, you might make the wrong feature choice, and lose out to competitors that simply avoid your terrible, costly decision.

2nd Mover Advantage

In Ethereum, one of the fundamental mistakes of its early development, its original sin, was the token standard. It was created just a few months after mainnet launch because the need for it was clear. One of the main initial use cases of a new programmable ledger, with zero infrastructure built around it, was simply to issue new tokens. Thus, it made sense to create a shared interface for them (sidenote: just a decade earlier, this was apparently a federal crime, see the story of Liberty Dollar. In a weird coincidence, the story of liberty dollar is also directly related to how I met my cofounder Konrad Urban).

The standard was called ERC-20, and it single-handedly held back crypto adoption and payments for perhaps an entire decade. It is, in my mind, a defining example of premature generalization.

What is ERC-20?

It is a simple standard. You can read the entire thing in three minutes. It explains a common standard you should follow if you want to issue your own token (onchain coin). For example, let's say you are the mayor of Atlantis and want to create AtlantisCoin. If you were to follow the ERC-20 standard, as everyone else does, you'd have to include in your program the following main functions:

  • a way to read the balance of anyone
  • a way to approve someone else to move your coins
  • a way to transfer coins to someone else (your own, or coins someone has allowed you to move)

That's basically it. It's pretty simple. There are a few other minor details, but this is basically how every single token on Ethereum today works.

The nice thing about this standard, and standards in general, is that they are predictable. If you're building Uniswap, or Aave, or even something like Polymarket, you'll have to interact with coins. Thanks to a standard existing, now you don't have to worry about integrating every single coin in existence! You can rest assured that all coins behave properly, follow the standard, and will work nicely with your protocol. Yay.

Unfortunately, the standard sucks. Unfortunately, your AtlantisCoin will still have to be compliant. Because if it isn't, it will not work with all the existing infrastructure, and will be as isolated as your legendary city.

The 3 (and a half) reasons ERC-20 sucks

1. You cannot attach information to a transfer

Whenever I go to my bank and make a payment, I'm given the option to add a reference. Whenever I make a card payment, metadata is attached. However, ERC-20 does not define any way to attach information to a payment. This is a huge, fundamental limitation and one that is hard to forgive. What is the impact?

  • Sender: "I paid invoice #12345"
  • Receiver: "Wait, which of these 50 transfers was yours?"

Fundamentally, it makes it so that you need to store information about a payment in some separate way, and then reconciliate. It's worse than just having another table in postgres; the whole point of blockchain is dealing with trust. Now, the payment is trustless, but the metadata isn't. It's not just unnecessary engineering complexity, it's a fundamental limitation of the standard. This impacts my own day to day as well: at peanut (the payments app I work on) if you do a deposit from a different chain, we have to create an ephemeral deposit address specifically for this transfer. There is no other way to attribute the incoming payment to your peanut user! 12.

It is simply obvious that a payment should have the option to have information attached to it. This makes a payment composable; you now can execute logic based on it, and build complex routing on top.

Now look at how a newcomer does it: Tempo, the L1 by Stripe, learned from Ethereum's mistakes and created their own payment standard: TIP-20. And of course they have transferWithMemo() as one of the standard functions.

2. The Two-Transaction Tax

You go to Uniswap. You want to do a swap. The parameters look good, let's do it! You click the button. Your MetaMask slowly loads, and a transaction pops up. You confirm it! It takes a while to confirm on Ethereum, but you're done. Wait, what's that? Another transaction? Why??

The ERC-20 standard sucks, that's why. You have to specifically first approve() Uniswap contract to be able to move your tokens. And only after that can you actually make the swap4. There are various solutions to this; ERC-223 solved it with transferAndCall() in 2017, ERC-777 also tried, but they found no adoption. Permit2 was an approach that found some adoption, but ultimately failed as well. Many apps today attempt to solve this by making a 1-time setup: do an infinite approval, and then never have to approve again. This has led to many losses; the latest one about 2 days ago, which finally prompted me to sit down and gather my thoughts and write this article. It's hard to guess overall losses, but probably a few hundred million, including the $120 million BadgerDAO hack.

And that's why premature optimization is so dangerous. We've had a decade of Ethereum, and for an entire decade, every user had to suffer essentially double the amount of clicks, double the amount of waiting time, and even almost double the amount of gas. The hundreds of millions of hacked funds are a big loss, but the real cost is the opportunity cost of not moving the world onchain faster3.

Today, in 2025, we're finally kinda finding a solution to this. It's called Account Abstraction (AA). You can now work around a terrible, two-transaction standard like ERC-20: just bundle the two transactions into one. Done.

Sadly, almost no one uses account abstraction today yet. However, adoption is growing, and it's a viable path forward, unlike ERC-223 or ERC-777, which were always destined to fail. In 2025 it is finally possible to have good UX, despite bad standards. Try out an app like Clave (or peanut, let me shill myself.).

3. Ether, and the absurdity of Gas

Practically all coins on Ethereum, certainly all the ones that matter, are ERC-20s. All except one.

The native coin of Ethereum, Ether, is not compliant. It is special. It is different.

Why? If you're a smelly nerd, you might give many smart nerdy arguments as to why. But you're wrong. Every sane wallet draws no distinction between ETH and other assets.

Vitalik's wallet

Vitalik's DeBank wallet. Notice ETH just looks like yet another token.

But, unfortunately, Ether IS different, in many ways. It doesn't emit transfer events, which trips up many an indexer. It doesn't comply with the rest of ERC-20 either. But ultimately, Ether is special because it is the ONLY TOKEN you can use to pay for a transaction5.

Having to explain to users why they need to hold a special gas token has held back Ethereum years. Imagine your bank telling you "sorry Bob, you cannot transact, you need $Santander tokens first"? Lunacy.

There have been attempts at patching (but never fully fixing) this. Permit2 was a great idea: make an infinite approval to a special contract, and then use offchain cryptographic signatures for the actual transfers. This fixed both problems 2) and 3), and almost 1) as well. But it required adoption, and it never achieved critical mass. Additionally, signing non-standard data has always been a problem in crypto, probably deserving of its own blog post.

Another patchwork approach was EIP-3009. Notably, stablecoin giant USDC adopted this. When we were initially working on payments via peanut links, we integrated this. It worked, for some definition of the word. Ultimately it was a short-term hack.

But what's a holistic solution? The way a newer blockchain like Tempo solves this: there is no special token, and all the supported tokens are usable to pay for gas. They do this via an enshrined AMM. This approach has its own limitations, but it is undoubtedly much nicer for the end user than the Ethereum experience of the last ten years.

And what is Ethereum's actual plan? You guessed it, Account Abstraction solves this as well. If you try an AA app like Peanut today, you'll be able to transact without ever having to think about gas. This is because of a new pseudo transaction type, userops. It is a generic, very flexible system (and a perhaps overly complex one) that took years to deploy. In a way, it seems to be the complete opposite of ERC-20. Shipped slowly in years instead of rushed, with extreme caution about every edge case7.

The Takeaways

There's a few takeaways I want you to get from here:

  1. Don't generalize prematurely. It will cost you dearly later.

  2. Don't generalize too late. It will cost you, in opportunity.

"Wait, aren't you contradicting yourself?" Yeah, I am. Find balance.

  1. If you're an app builder, build with AA.

There's no reason to be building apps with old school transactions any more. It should be obvious that you should be using Account Abstraction today. And if you've never built on blockchain before because it seemed clunky and bad: this is no longer the case. In 2025, blockchain can feel like web2.

A bad standard was not the only reason that blockchain adoption—specifically for payments—has been so slow. It's been 15 years since the Bitcoin whitepaper, 10 years since Ethereum mainnet, and crypto payments are still only a tiny slice of real-world payments. Why is crypto so slow? Internet adoption was faster, and AI took the world by storm.

Or did it? Actually, it didn't. AI had a horribly long "AI winter" that it went through, and it was only in 2012 that the field revived again. A full decade later, in 2022, enough infrastructure had been built, and hardware was ready. ChatGPT was released and the flood began.

I believe we're now approaching the same critical point AI was at roughly three years ago: all conditions have been, or are close to being, met. The infrastructure is ready. We now have cheap, scalable transactions6. We have good on- and off-ramps. We have tools for proper self-custody. And, most importantly, we have built systems so complex and advanced they can even defeat such a terrible standard as ERC-20.

The future is bright.

Footnotes


  1. This is not only terrible UX, but also unnecessarily complex. In fact we work with a 3rd party here: Daimo. Doing this self-custodially is hard. Most of the industry uses Relay for this, a simpler, but custodial provider. 

  2. In principle, Ethereum transactions can contain a memo. In practice, this is not part of the ERC-20 standard, nor is it usable onchain, the transfer event doesn't emit it, wallets don't show it, it's expensive and incompatible with e.g. UserOps, and generally has 0 adoption. 

  3. I also blame ERC-20 in part for enabling the likes of FTX. Terrible onchain UX made custodians proliferate. They could make the interface easy for their users. Today, the minority of users have custody; most are on Binance. 

  4. The approve pattern was actually a workaround for a bug in the early EVM days. The workaround, however, became permanent. Nothing is more permanent than a temporary fix. 

  5. Vitalik has mentioned that he expected account abstraction to arrive within a year of Ethereum launching, which influenced some of the early design decisions around ETH's special status. It took almost a decade instead. 

  6. Many people ask me how we are able to pay for every users gas. This confuses them. The answer is that L2 transactions cost about a tenth of a cent nowadays. We've come a long way. 

  7. Interestingly, Tempo does not seem to care too much about a flexible system here. They've taken a few parts they find important about AA (gas abstraction, batched calls, and some better auth management), and ignored the rest. I think this might've been the correct call five years ago, but launching an L1 in 2025 with this approach is shortsighted and dumb. References here and here