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’sERC2771Forwarder. It checks a signed request and passes it on to the target.GuestBook, anERC2771Contextcontract. Each entry records the person who signed, not the relayer that paid.- 26 tests that run under both
forge testandhardhat test, covering direct calls, forwarded calls, expiry, replays and bad signatures. - A relayer server with
POST /relayandGET /health. It only pays forGuestBook.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
.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
Terminal
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.
Links
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.