Skip to main content
Let users with 0 tBOT write to a contract: they sign a message, and your relayer sends the transaction and pays the gas.
Ready. This template is published in uzolabs/templates and has been deployed and verified on testnet. It’s a learning template and hasn’t been audited. Use test funds only.

What it does

  • UzoForwarder, OpenZeppelin’s ERC2771Forwarder. It checks a signed request and passes it on to the target.
  • GuestBook, an ERC2771Context contract. Each entry records the person who signed, not the relayer that paid.
  • 26 tests that run under both forge test and hardhat test, covering direct calls, forwarded calls, expiry, replays and bad signatures.
  • A relayer server with POST /relay and GET /health. It only pays for GuestBook.sign, checks every request with the forwarder first, and rate-limits each signer and IP address.
  • npm run sign, which creates a brand new wallet with 0 tBOT and signs through the relayer.
  • A web app with a “Sign for free” button. The wallet asks for a signature, never a transaction.

Quick start

You need Node.js 20.19+, Foundry, a browser wallet and two funded test wallets: a deployer and a relayer. See Prerequisites.
Terminal
In .env, paste the deployer key after PRIVATE_KEY= and the relayer key after RELAYER_PRIVATE_KEY=. Keep them separate, because the relayer server holds its key while it runs. Then:
Terminal
Leave the relayer running. In a second terminal, start the web app:
Terminal
Open http://localhost:5173, connect a wallet that holds 0 tBOT, type a message and click “Sign for free”. To test from the terminal instead, run npm run sign -- "gm from the terminal".

How it works

The forwarder appends the signer’s address to the calldata. GuestBook reads it through _msgSender(), so the entry’s author is the person who signed. Each request has a nonce and a 10 minute deadline, so it works once only. The walkthrough covers each check the relayer makes.

Tested on testnet

Both toolchains were run on BOT Chain Testnet on 1 October 2026, with a separate relayer wallet holding 10 tBOT. Each deploy used 1,455,763 gas for both contracts (0.02911526 tBOT at 20 gwei). Each relayed message used between 96,439 and 136,073 gas, all paid by the relayer. A second wallet also signed two messages from the web app, and its balance and transaction count didn’t change. These are example addresses from one run. Your deploy gets its own.

Walkthrough

The forwarder, the relayer’s checks and the web app.

Customize

Relay calls to your own contract.

Source on GitHub

The template folder and its README.

Meta-transactions guide

The same pattern built by hand.

Gasless app template walkthrough

A file-by-file tour of the contracts and scripts in the Gasless app template.

Customize the Gasless app template

Ideas and steps for turning the Gasless app template into your own project.
Last modified on October 2, 2026