betterERC
Docs/Start here

Overview

What this framework is, what it is not, and the single call that makes the rest of these pages optional.

All docs

Solana's runtime gives token extensions their guarantees for free. One program owns every mint, walks each account's extensions in a fixed order, and no token author can change that order. The EVM has no equivalent. Every ERC-20 is its own program, and an integrator who wants to know how one behaves has to read its source, or simulate a transfer and hope the result generalises.

This framework is the missing half. Not new capabilities — fee-on-transfer, pausing, freezing and hooks all exist today — but a way for a token to say what it does, in a form that costs one view call to read and is fixed for the life of the deployment.

The idea in one function

Integrator.sol
uint256 flags = IERC20Behavior(token).behaviorFlags();

One word. Every way this token departs from a plain ERC-20. Each bit that is set names the page you need to read, and a word of zero says the token departs in no way at all.

And the question underneath it

That word is produced by the token's own code, which makes it a claim. A token declaring nothing while withholding two percent of every transfer has said exactly what an integrator hoped to hear. So there is a second question, and it has an answer that does not involve asking the token anything.

Integrator.sol
if (BERCVerification.isClonedFrom(token, BERC_RUNTIME_V1)) {
    // The answers come from the runtime you vetted and pinned.
}

Canonical tokens are minimal-proxy clones of one shared runtime. Those forty-five bytes are a fixed prologue, an address and a fixed epilogue — nowhere to hide behaviour. One bytecode read establishes which tier a token is in, and the tier decides what its declarations are worth.

Four layers

Declaration
The discovery surface: extensions, hasExtension, extensionData, behaviorFlags and accountState. What is installed, how it is configured, and what that means for a caller. None of it sits on the transfer path.
Interfaces
One interface per extension — on-chain metadata, transfer fee, transfer restriction, non-transferability, transfer hook. Descriptive names, and no draft ERC number that would have to be renumbered later.
Implementation
Abstract modules on OpenZeppelin v5 that a token assembles by inheritance, plus three deployment shapes: immutable, upgradeable behind a UUPS proxy, or a clone of the shared runtime.
Verified runtime
One deployed contract every canonical token clones, and a library that recognises a clone of it from bytecode alone. This is what turns a declaration from a claim into a property of code you reviewed.

How to read the rest

If you are integrating a token somebody else deployed, establish the tier first, then read the five-minute version, then the page for each bit the token actually sets. If you are building a token, the reference section describes what you are declaring and the building section describes how to assemble it.

The interfaces are deliberately not tied to any draft ERC number, so adopting one later does not require redeploying anything.