Seed Protocol
Infrastructure

Costs and who pays

Where the money goes when Seed Protocol publishes: gas for EAS attestations on OP Sepolia in each wallet setup, and Arweave storage paid by the bundler behind the upload API or by the user through Turbo, with live Arweave prices, the 256 KiB minimum and what each party funds.

A publish costs money in two places: gas on the chain where the attestations go, and storage on Arweave for files, images and Html bodies.

For the estimate API (estimatePublishCost, watchPublishCost, usePublishCostEstimate), see Cost estimates and payment in the publish package reference.

Summary

CostPaid inWho pays by default
Attestation gas (EAS on OP Sepolia)Testnet ETHthirdweb's paymaster, if the thirdweb project behind your client ID sponsors gas. Otherwise the publishing account
Schema registration gasTestnet ETHThe same, from the owner's account
Arweave storage, operator-paid (the default)Real AR (Arweave mainnet)The bundler's wallet, run by the upload API's operator
Arweave storage, user-paid (payment: { storage: 'user' })Turbo creditsThe user, from the signer address's Turbo credits (or an app's shared credits)

The payment option in @seedprotocol/publish states who pays gas and storage, and makes initPublish throw on a config that contradicts it. See The payment option.

Arweave has no testnet, so storage is on Arweave mainnet even while the attestations are on OP Sepolia: every test upload costs real AR for whoever pays it, and stays public for good. See What "permanent" means today.

Gas

Attestations go to EAS on OP Sepolia, a testnet, so gas is paid in testnet ETH that has no market value. The public OP Sepolia RPC reported a gas price of about 0.001 gwei (eth_gasPrice = 1,000,250 wei) on 2026-10-18.

With the default thirdweb setup, the publishing account is an ERC-4337 smart account (the ManagedAccount), and its transactions are UserOperations that a bundler submits. @seedprotocol/publish asks thirdweb's paymaster to pay for them (thirdweb.sponsorGas, true by default), but asking isn't paying: whether the paymaster sponsors is set in the thirdweb project behind your thirdwebClientId, by whoever set the project up.

SetupWho pays gas
ConnectButton, default configThe ManagedAccount's UserOps go through thirdweb's bundler with sponsorGas: true, which asks thirdweb's paymaster to pay. A new user's first publish sends one more UserOp first, which deploys the ManagedAccount, on the same terms. If the thirdweb project doesn't sponsor, turn sponsorship on there, or set sponsorGas: false and fund the ManagedAccount with testnet ETH.
ConnectButton with useModularExecutorAs above for publishes. The in-app wallet's own transactions (deploying the ManagedAccount with autoDeployManagedAccount, installing the executor, bootstrapping its EIP-7702 account) also request sponsorship in 'EIP7702' mode. In modularWalletMode: 'EOA' the in-app wallet pays them.
thirdweb.sponsorGas: false, or payment: { gas: 'user' }Nothing is sponsored. The ManagedAccount, and the in-app wallet in 'EOA' mode, need ETH. This is the setup for a local chain with no paymaster.
useSeedWallet or fromEip1193Provider, accountMode: 'eoa'The user's wallet pays every transaction. It attests straight to EAS only when the wallet says it's an EOA (kind: 'eoa', which the adapters set); see EOA: no account abstraction.
accountMode: 'eip7702' with bundlerUrlUserOps go through bundlerUrl with paymasterUrl (or, when unset, bundlerUrl) as the paymaster. Whoever runs that paymaster pays, if it sponsors. With payment: { gas: 'user' } no paymaster is attached and the account pays its own gas.
Session-key automationThe sender you build decides. The guide's example sets sponsorGas: true on a thirdweb smart wallet.

To state who pays instead of relying on these defaults, set payment.

What uses gas: one multiPublish per publish from a smart account (one per item when a relation or list names another item published with it). From a plain wallet, each item takes one EAS attest for a new Seed, one for a new Version, and one multiAttest for its properties. Add two transactions for each EAS schema an item's models and properties need that isn't registered on the chain yet (the registration and a naming attestation). Revoking costs one transaction per schema.

Account abstraction: bundler and paymaster explains the parts and how to run without sponsorship.

Arweave storage

Arweave charges once, up front, for permanent storage. You can ask any gateway for the current price of storing a number of bytes:

curl https://arweave.net/price/1024

The answer is in winston: 1 AR = 10¹² winston.

Live prices

From https://arweave.net/price/{bytes} on 2026-10-18 at 16:36 UTC. Prices follow the network and the AR market and change all the time, so treat these as an illustration and fetch your own.

Data sizePrice (winston)Price (AR)
1 byte3,408,198,0400.00341
1 KiB3,408,198,0400.00341
256 KiB3,408,198,0400.00341
256 KiB + 1 byte6,775,166,9460.00678
512 KiB6,775,166,9460.00678
1 MiB13,509,104,7590.0135
10 MiB134,719,985,3820.135

Two things stand out:

  • There's a 256 KiB minimum. Arweave prices each transaction's data in 256 KiB chunks and rounds up, so a 1-byte file costs the same as a 256 KiB one.
  • Above that, it's roughly linear. About 0.0135 AR per MiB at these prices.

estimatePublishCost prices a publish's uploads at the total size of their signed data items (each file plus its ANS-104 header and tags) or 256 KiB, whichever is larger; see arweave.chargedBytes in Cost estimates and payment.

The bundler path

Publishes upload signed ANS-104 data items. The upload API forwards them to a bundler, and the bundler's wallet pays to post them. The data item signer is an Ethereum key and needs no AR. Seed's own gateway is private (Seed's gateway).

A bundle is one L1 transaction holding many data items, priced by its total size like any other transaction. The 256 KiB minimum applies to the bundle, not to each item, so small files share it, and the operator pays the network roughly by the bytes it bundles. Whether the bundler accepts your items is up to its operator; see The bundler path for the request flow.

User-paid storage: Turbo

With payment: { storage: 'user' }, the publish package sends the signed data items straight to Turbo (ArDrive's bundling service, upload.ardrive.io by default) instead of the upload API. Turbo bundles them like any bundler, and charges the signer's address in Turbo credits (winc, priced like winston), which users buy with a card or crypto. Items up to Turbo's free size limit are free. An app can pay instead by sharing its own credits with users and listing its address in userStorage.paidBy.

Nobody running an upload API pays for these items. The publish checks the signer's balance first and fails with InsufficientStorageCreditsError rather than upload part of a publish. Both the publish and estimatePublishCost read Turbo's current free limit from its /v1/info, and the estimate falls back to 100 KiB when Turbo doesn't answer; Turbo reported 105 KiB (107,520 bytes) on 2026-10-27. See Uploads and ANS-104 data items.

What to fund

You runYou fund
An app with ConnectButtonThe thirdweb project's gas sponsorship, if you enable it. Otherwise your users need testnet ETH.
An app with an injected wallet in 'eoa' modeNothing. Users pay gas.
An upload APIIts bundler's wallet, in real AR
An app with payment: { storage: 'user' }Nothing for storage. Users buy Turbo credits, unless you share an app wallet's credits through userStorage.paidBy
A local twinBoth accounts, with twin:fund (see Local twin)

On this page