Index of every page on this site: llms.txt
All skills
base avatar

/vibenet

@ef8bcd5 official
by basebase/skills120 stars
130
Run it yourself

Build on vibenet — Base's devnet for native account abstraction (EIP-8130), payer gas sponsorship (ERC-8168), and Cobalt 200ms native blocks. Use whenever the user mentions vibenet, EIP-8130, ERC-8168, 8130 accounts, native account abstraction, session keys, actors, policies, payers, gas sponsorship on Base, 200ms blocks, Cobalt, BaseTime, timestampMs / blockTimestampMs, sub-second or millisecond block timestamps, migrating from Flashblocks, or newHeads / WebSocket streaming on vibenet — or is writing code that creates or operates 8130 smart accounts, authorizes session-key actors, sends batched calls, sponsors gas with a payer, queries or streams vibenet blocks, times a transaction's inclusion, or wires a frontend/script against the vibenet devnet or Base Sepolia.

Use this Skill: https://skilld.dev/gh/base/skills/vibenet

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencespayer-sponsorship.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Payer gas sponsorship (ERC-8168)

Sponsoring gas for 8130 accounts with a payer service — the path to gasless onboarding (account creation + first transaction with zero user ETH). For account creation and core concepts, read eip8130-accounts.md first.

A payer is a service that co-signs payer_auth to pay gas (sponsored or in ERC-20). The hosted vibenet payer lives at https://api.vibes.base.org/api/vibenet/account/payer and supports both ERC-8168 modes:

  • mode: "send" (default) — payer co-signs and submits (payer_sendTransaction)
  • mode: "sign" — payer co-signs only; you broadcast with eth_sendRawTransaction

Sponsor a first transaction (gasless onboarding)

import type { Hex } from "viem";
import { createPayerClient, sendSponsoredCalls } from "viem/eip8168";
import { waitForTransactionReceipt } from "viem/eip8130";

const payerClient = createPayerClient({
  url: "https://api.vibes.base.org/api/vibenet/account/payer",
});

// Default mode:"send" — payer co-signs and broadcasts, resolving with an
// OBJECT: `{ transactionHash }`. Destructure it. (The declared return type says
// otherwise — see the note below — so TypeScript needs a cast.)
const { transactionHash: hash } = (await sendSponsoredCalls(client, {
  account,
  payerClient,
  accountChanges: [account.createChange], // deploy rides in the first sponsored tx
  calls: [{ to: account.address, value: 0n, data: "0x" }],
  context: { flow: "transact" }, // budgets free grants per (sender, flow)
})) as unknown as { transactionHash: Hex };
const receipt = await waitForTransactionReceipt(client, { hash });

No faucet call and no user ETH is needed anywhere in this flow — the payer's payer_auth makes the protocol debit gas from the payer, not the sender. Gas only: if the sponsored calls transfer value, the account still has to hold that value — a sponsored 0.001 ETH tip from a zero-balance account reverts, a sponsored zero-value call does not.

Sponsored value transfers must be wallet-wrapped. sendTransaction auto-routes value-bearing calls through the account, but sendSponsoredCalls does not: calls: [{ to, value, data }] throws EIP-8130 calls cannot carry \value` on the wire(live-confirmed on the current branch). Wrap the phase withencodeWalletCalls` first — and remember the account must actually hold the value:

import { encodeWalletCalls } from "viem/eip8130";

const { transactionHash } = (await sendSponsoredCalls(client, {
  account,
  payerClient,
  calls: encodeWalletCalls({
    account: account.address,
    calls: [[{ to: recipient, value: parseEther("0.001"), data: "0x" }]],
  })[0], // one phase → one wallet-routed executeBatch call
})) as unknown as { transactionHash: Hex };

For self-submit (e.g. custom RPC / retry control), pass mode: "sign" — the call then resolves with the signed raw transaction, which you broadcast yourself with eth_sendRawTransaction.

The declared return type is wrong. SendSponsoredCallsReturnType is typed as a union of hex strings (SendTransactionReturnType | SignTransactionReturnType), but mode: "send" resolves with { transactionHash } at runtime — live-confirmed against the hosted payer. Passing the raw result into waitForTransactionReceipt fails at the RPC layer with invalid type: map, expected 32 bytes, which points nowhere near the cause. The union also isn't assignable to Hex, so narrowing needs as unknown as.

Wire protocol (JSON-RPC over the payer URL)

Under the hood sendSponsoredCalls runs the ERC-8168 flow: fetch terms with payer_getTerms, build and sign sender_auth with payer set and payer_auth empty, then hand off via payer_sendTransaction (send mode) or payer_signTransaction (sign mode). payer_getTerms + payer_sendTransaction are the required pair every payer implements; payer_signTransaction is optional (advertised in the terms' methods). Rejections come back as JSON-RPC error -32000 with a data: { code, reason } envelope — branch on the string code (e.g. BUDGET_EXHAUSTED, SENDER_LIMIT_REACHED, whose context includes a validFor retry hint). Full types: src/eip8168/types.ts on the fork branch.

Notes

  • Subsequent sponsored txs omit account.createChange — only the first tx carries it.
  • Retry actor is not bound right after a self-paid deploy. Account config can propagate ~1 block behind the receipt (the same lag as eth_getCode and config read-backs), and the payer validates against the lagging state — a sponsored tx sent in that window is rejected with EIP-8130 validation failed: actor is not bound, surfaced as viem's InvalidInputRpcError: Missing or invalid parameters. Neither message points at timing. On 2s blocks this was live-reproduced (fails immediately, succeeds ~6s later); on today's 200ms vibenet a sponsored send ~0.8s after the deploy receipt was accepted first try. Either way: retry on actor is not bound (sub-second gaps suffice now) or wait for the account's code read-back.
  • The payer itself can run out of ETH, and it looks nothing like a budget rejection: InvalidInputRpcError wrapping Broadcast failed … insufficient funds for gas * price + value: have <n> want <m> from an internal http://base-client:8545 URL (live-hit 2026-08-21). The have figure is the payer wallet's balance. Diagnose with payer_getTerms → the payer address → eth_getBalance; on the devnet the fix is to faucet-drip the payer address itself. Also: the terms may advertise only a token (USDV) offer while sponsored payer_sendTransaction still works — don't gate on the offer list.
  • context.flow lets the hosted payer budget free grants per (sender, flow) pair; pick a stable string per product surface (e.g. "onboarding", "transact").
  • Payer standard: https://eip.tools/eip/8168 (viem module: src/eip8168 on the fork branch).

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

2 warnings1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill provides a specialized development environment for Base's Vibenet devnet. It includes a setup script that clones an experimental fork of the viem library from GitHub and performs local build and installation steps. While standard for developers building on experimental protocols like EIP-8130, these actions involve executing build scripts from a non-official repository during environment setup.

  • Socket1mo

    2 alerts: gptAnomaly

  • Snyk1mo

    Risk: MEDIUM · 1 issue

Signed by skilld at ef8bcd5. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated last month

README badge

README badge for base/skills/vibenet