Skip to Content

Gas Tank

The Gas Tank pays network fees on behalf of WaaP users, so they can transact without holding native tokens for gas. It comes in two forms:

  • Personal gas tanks: every WaaP user has one, funded and used entirely from inside the wallet. No integration work is needed on your side.
  • Sponsor gas tanks: a pre-funded tank owned by your project. Once configured, transactions your users make on your dApp are paid from your tank instead of theirs, so they never think about gas at all.

This guide covers setting up sponsorship for your project. Everything is managed in the Gas Tank Console with your WaaP wallet.

The gas tank is not a paymaster. It does not co-sign or wrap your transaction. The user signs the exact transaction they reviewed, the gas tank transfers gas to their wallet, and then that unchanged transaction is broadcast. Nothing about the transaction differs from an unsponsored one.

Sponsoring your users’ gas

1. Create a project

Open the Gas Tank Console and sign in with your WaaP wallet. Opening your project creates it if it doesn’t exist yet: you get a project ID and an empty sponsor gas tank administered by your wallet.

2. Pass your project ID to the SDK

import { initWaaP } from "@human.tech/waap-sdk"; initWaaP({ project: { projectId: "<your-project-id>", // ...other project fields, e.g. name, logo }, config: { // ...UI configuration }, });

config is UI configuration (auth methods, styles) and has no projectId field. A project ID passed there is silently ignored and nothing is ever sponsored.

The same field works on the single-chain entry points, initWaaP({ chain: 'sui', project: { projectId } }) and initWaaP({ chain: 'solana', project: { projectId } }), and on initWaaPMulti.

With the project ID set, eligible transactions from your dApp are checked against your project’s gas tank and sponsored automatically.

3. Configure allowlists

Sponsorship is scoped by two allowlists, managed in the Gas Tank Console:

  • Targets: what your tank pays gas for, per chain. What counts as a target depends on the chain:

    ChainAllowlisted targetMatching
    EVMTransaction’s top-level to address (contract or EOA)Case-insensitive
    SuiEvery Move call package ID and TransferObjects recipient encoded as a pure address inputCase-insensitive, zero-padding ignored
    SolanaEvery top-level instruction program ID in the compiled messageCase-sensitive base58
  • Domains: the exact site origins allowed to request sponsorship. Enter only scheme://host[:port], for example https://app.example.com, without a path, query string, or fragment.

A transaction is sponsored only when the requesting origin and every target extracted from the transaction match. Anything outside the allowlists is not sponsored and the user pays gas as usual. The target allowlist is per chain, so the same address on another chain is a different entry.

The settings use [chain, target] tuples. EVM chains use numeric chain IDs; Sui and Solana use their network references:

{ "transactions_allowed_to": [ [42161, "0x0000000000000000000000000000000000000001"], ["sui:mainnet", "0x0000000000000000000000000000000000000000000000000000000000000002"], ["solana:mainnet", "11111111111111111111111111111111"] ], "domains_allowed": ["https://app.example.com"] }

Targets are extracted from the transaction structure, not from a full execution trace.

EVM allowlist examples

EVM extracts only the transaction’s outer to address:

  • A native ETH transfer targets the recipient address.
  • USDC.transfer(recipient, amount) and USDC.approve(spender, amount) both target the USDC contract. The recipient or spender encoded in calldata is not a target.
  • A router, proxy, or multicall transaction targets only the outer router, proxy, or multicall contract. Tokens, pools, implementations, and nested call destinations are not extracted.

For example, these entries allow a direct Arbitrum transfer to the first address and calls to the Arbitrum USDC contract:

[ [42161, "0x1111111111111111111111111111111111111111"], [42161, "0xaf88d065e77c8cc2239327c5edb3a432268e5831"] ]

Calling Permit2 directly requires a Permit2 entry, but approving Permit2 as an ERC-20 spender requires the token contract entry instead. Contract creation has no to address and cannot be sponsored.

Sui allowlist examples

Sui extracts each MoveCall.package and each TransferObjects recipient that is encoded as a 32-byte pure address input. Duplicate targets are collapsed. For a programmable transaction containing:

MoveCall: 0xabc::pool::swap MoveCall: 0x2::coin::value TransferObjects: output coin to 0xbbbb...bbbb

the allowlist needs all three targets:

[ ["sui:mainnet", "0xabc"], ["sui:mainnet", "0x2"], ["sui:mainnet", "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"] ]

Sui targets are lowercased and left-padded to 64 hex characters. Package IDs used only as type arguments, object and coin IDs, SplitCoins, and MergeCoins are not targets. A transaction with no Move call and no extractable transfer recipient has an empty target list and is not eligible for project sponsorship.

If a transaction explicitly transfers its result to the current user, that user’s address is a target and must be allowlisted.

Solana allowlist examples

Solana extracts each unique top-level instruction program ID in the compiled message. A managed native SOL transfer contains Compute Budget and System Program instructions, so it needs both entries:

[ ["solana:mainnet", "ComputeBudget111111111111111111111111111111"], ["solana:mainnet", "11111111111111111111111111111111"] ]

An SPL token transfer that creates the recipient’s associated token account contains Compute Budget, Associated Token Account, and SPL Token instructions:

[ ["solana:mainnet", "ComputeBudget111111111111111111111111111111"], ["solana:mainnet", "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"], ["solana:mainnet", "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"] ]

A swap must allow every top-level program present in its compiled instructions, such as Compute Budget, the swap program, and SPL Token. Recipient wallets, mints, token accounts, pools, vaults, and programs invoked only through CPI are not extracted. Sponsored instruction program IDs must be present in the message’s static accounts. Solana IDs remain case-sensitive.

4. Fund the tank

Fund your tank from the Gas Tank Console. The deposit is sent from your admin wallet and credited to the project. The current balance is shown in the console, and each sponsored transaction is deducted from it.

A tank holds one balance per asset, and each chain is paid in its own asset: EVM sponsorship spends the ETH balance, Sui spends SUI, Solana spends SOL. Fund every chain you intend to sponsor on.

For the ETH balance, the amount shown is the gross balance and the amount spendable on gas is 90% of it. Each sponsored transaction deducts its gas cost ÷ 0.9.

When sponsorship applies

There is no SDK method to call at send time. When a transaction is eligible, WaaP sponsors it during send; when it is not, the transaction proceeds normally and the user pays gas. Your integration code is identical either way.

The order matters, and it is deliberate:

  1. The user reviews and signs the exact transaction.
  2. Eligibility is re-validated server-side. The check at preparation time is advisory and is not trusted at send time.
  3. Gas is transferred to the user’s wallet.
  4. The funding is observed on-chain.
  5. The original, unchanged transaction is broadcast.

Signing happens before funding, and broadcast happens only after funding is observed. Preparing a transaction never spends or reserves tank balance, so a prepared-then-abandoned transaction costs nothing.

What is not eligible

  • Any chain outside the supported list below.
  • Contract creation.
  • A target or domain outside your project’s allowlists.
  • Anything when the tank’s balance is insufficient.

Rejections are deliberately generic in production responses. The gas tank owns its own identity, allowlist, and balance rules, and does not leak which one failed. In local development the bounded detail is retained so you can tell a missing tank from a sender mismatch or an empty balance.

Supported chains

  • EVM: ETH-native mainnet chains: Ethereum, Optimism, Base, Arbitrum, zkSync, Shape, World Chain, Linea, and Scroll. Chains whose native token is not ETH (such as Polygon, Gnosis, Avalanche, or Celo) cannot be sponsored. See Supported Networks for the full chain list.
  • Sui: sponsored from the project’s SUI balance when every Move call package ID and every TransferObjects recipient encoded as a pure address input is allowlisted.
  • Solana: sponsored from the project’s SOL balance when every top-level instruction program ID in the compiled message is allowlisted.

Testnet transactions are never sponsored.

A chain appearing in some other registry does not start being sponsored as a side effect. Adding one here is a deliberate decision.

Sui sponsorship works by having the sponsor’s own coin pay for gas, so a sponsored transaction may not take its value from transaction.gas. A plain SUI transfer built that way can never be sponsored, however the project is configured. Move a non-gas asset instead.

Solana also refuses to leave an account below the rent-exempt minimum, so a user account holding no SOL at all cannot move SOL however well funded the project is.

Security notes

  • The gas tank never has access to user funds. It only ever sends gas money to the user’s address before a transaction.
  • Wallet addresses are resolved server-side from the user’s keyshares; the sponsorship API never trusts a client-supplied address.
  • The requesting origin is verified server-side against your domain allowlist; a page cannot claim an origin it is not served from.
Last updated on