Docs · Crypto

Token Offerings

Presenting a token your workspace owns, and why deploying one is not built.

What v1 does

It registers a token that already exists. A builder supplies a network and a contract address, and the name, symbol, decimals and total supply are read from the chain, never taken from the form.

That distinction matters: a form that accepts a symbol lets anyone register USDC's address and label it whatever they like. Reading means the page shows a fact about the contract rather than a claim about it.

VerifyTokenOfferingJob does the reading. It refuses an address with no code at it (an externally owned account is not a token) and an address whose contract does not answer the ERC-20 reads.

Why deploying is not built

Deploying a new token means shipping compiled bytecode in a paid kit, and that is a trust claim rather than a feature. It only holds with a reproducible build: committed Solidity source, an exact compiler version and settings, and a documented command that reproduces the bytes byte-for-byte. Until that exists, registering is the honest offering: no gas, no bytecode to take on trust, and no issuance liability created by the kit.

If you add deploying, it needs all of this, and none of it is optional:

  • Reproducible build. Source, solc version and settings, and a command a buyer can run.
  • A boring contract. Fixed supply minted in the constructor, and no owner, mint, burn, pause or upgrade function. Each of those is a rug vector and a support burden.
  • CREATE2 rather than plain CREATE. An ERC-4337 UserOperation has no contract-creation form, so to: null from a smart account fails or is silently rewritten. On Base a large share of users are Coinbase Smart Wallet. CREATE2 also makes double-submission impossible: the same salt and init code cannot create twice.
  • A mainnet guard. ONCHAIN_ALLOW_MAINNET_WRITE, plus type-the-symbol confirmation on a distinct page rather than a modal. Modals get dismissed; pages get read.
  • Honest gas. On Base and every OP-stack chain the L1 data fee is a separate component that eth_estimateGas omits, and for contract creation with multi-KB calldata it usually dominates. And do not put a gas field in the transaction you hand the wallet: if your limit is low the transaction runs out of gas, the user loses the entire fee and gets nothing.

The scope boundary

Deliberately out, because this is where the money and the liability concentrate:

  • No sale, no bonding curve, no fundraising contract. A sale contract needs an owner to withdraw proceeds, which reintroduces every rug vector a boring token removes.
  • No LP creation. It is the next thing everyone asks for, it looks like a small integration, and it is not: creating a market is arguably distribution, and "the founder pulled the LP" is the canonical rug story.
  • No airdrop execution. A Merkle claim contract holds value and needs an owner to sweep unclaimed tokens, undoing everything the boring contract achieved.

The public page

One page in this module is public: /t/:public_slug, for offerings that are both live and published.

It is a deliberate, narrow exception to the kit's tenancy rule, written to be obviously so. It is found by a random 16-character slug, never by id, because an id-addressed public route is enumerable, which would turn "share this link" into "read every workspace's tokens". Registering a token does not publish it; the builder sets published explicitly.

You are the issuer

The registration form carries this, and it belongs there rather than only in a doc, because that is the screen a person actually reads:

One Shot ships code. When you present or issue a token, you create it, you distribute it, and you are the person a regulator, an exchange, or a holder will look to. Issuing or promoting a token is a regulated activity in many jurisdictions and the rules differ by country. This is not legal or tax advice.