Gas Subsidies
Gas Subsidies let a project pay the gas fees on behalf of its users.
Users interact with your app without holding any native S tokens. You decide which transactions get covered, and the network deducts the fee straight from a fund you top up.
Why it matters
Native gas tokens are the single biggest onboarding blocker for new users. With Gas Subsidies, a wallet with zero S balance can still call your contract, mint an NFT, or complete an onboarding flow. The transaction fee is settled directly on-chain, not by a relayer or a separate meta-transaction layer.
How a transaction gets sponsored
A user simply signs and sends a transaction with gasPrice = 0. The Sonic node checks whether any active fund covers it. If one does, the fee is paid from that fund instead of being rejected for insufficient balance. Funds are matched by increasingly broad rules, checked in this order:
Account + nonce — Covers one specific transaction, identified by sender and nonce. Useful for sponsoring a single, pre-approved action.
Account + operation — Covers a specific account calling a specific function on a specific contract.
ERC-20 approval — Covers a token approval, but only once per spender and only while the user's current allowance is zero and their balance is non-zero — prevents repeated free approvals.
Operation — Covers any account calling a specific function on a specific contract — e.g. every call to
mint()on your NFT contract.Bootstrap — Covers a new account's first three transactions network-wide, regardless of destination — a general on-ramp for newcomers.
Contract — Covers every transaction sent to a given contract, whichever function is called.
Account — Covers every transaction sent from a given account, wherever it's headed.
The node stops at the first matching fund that has enough balance to cover the fee, so narrower, more targeted funds always take priority over broad ones.
Funding and withdrawing
Anyone can contribute native tokens to a fund — there's no need to be its creator. Each fund tracks the total available balance and every contributor's share of it.
sponsor(fundId)
Sends native tokens into the chosen fund. The sender's contribution is recorded proportionally.
withdraw(fundId, amount)
Withdraws up to your proportional share of what's left in the fund. Blocked from inside a sponsored transaction itself, to prevent draining a fund it's currently paying for.
getAvailableFunds(fundId)
Reads the current balance available to cover sponsored transactions.
Fund IDs are just hashes. Each sponsorship rule (account, contract, operation, …) has a matching helper — e.g.
contractSponsorshipFundId(address)— that derives itsfundIddeterministically. To sponsor "all calls to my contract," you call that helper to get the ID, then send funds to it.
Code examples
The examples below demonstrate usage with ethers.js. A sponsor deposits into the fund matching the rule it wants to cover. A user sends the transaction with gasPrice = 0 like normal, using whatever library or wallet they prefer.
Sponsor: funding an ERC-20 approval
This funds the ERC-20 approval rule for a specific (token, spender) pair, by deriving its fundId from the exact approve calldata being sponsored.
User: sending the sponsored (zero-gas) transaction
The user's side needs no awareness of the fund at all. Set gasPrice: 0n and send the call as usual. If a matching fund has balance, the Sonic node covers the fee; otherwise the transaction is rejected like an underpriced tx.
Operational notes
Fees paid out of a fund are burned through the SFC contract, the same as ordinary gas fees — subsidies change who pays, not how the fee is settled.
Last updated

