(Docs)
How to put an agent on a leash.
Leashwick is one contract, LeashVault, on Robinhood Chain. This page covers the owner side, the agent side, every limit the contract enforces, and what has not been audited.
(01) Owner guide
Open, fund, watch, stop.
- Connect a browser wallet in the console. It switches to Robinhood Chain for you.
- Open a leash: the agent's address (the key your agent signs with), a daily cap in ETH, 1 to 20 allowlisted destinations, an optional public label, and an optional first deposit. You become the leash owner.
- Give the agent its leash id (shown after the transaction) and a little ETH on its own address for gas. A spend costs about 0.000002 ETH in gas at today's fees.
- Watch receipts on the home page or on Blockscout. Every spend emits a
Receiptevent. - Change things whenever you want:
fund,withdraw,setCap,allow,disallow,stop,resume. Only the leash owner can call these (fund is open to anyone).
The agent address is fixed for the life of a leash. To rotate an agent key: stop the leash, withdraw, and open a new one for the new address.
Look up any leash without a wallet: enter its id or an address in the console's Look up tab, or link to leashwick.pro/?leash=7.
(02) Agent integration
One function: spend().
The agent signs spend(id, to, amount, memo) from its own address. to must be on the allowlist, amount is in wei and must fit in what is left of today's cap, and the leash must cover amount plus the fee. memo is 32 public bytes (an invoice number, a task id). Before spending, the agent can read maxSpendNow(id): the largest amount spend accepts right now, with cap, balance, fee and stop all included.
viem (Node or browser)
Foundry cast
When spend reverts
| Error | Meaning |
|---|---|
| NotAgent() | The signer is not this leash's agent, or the id does not exist. |
| Stopped() | The owner hit stop. |
| NotAllowed(to) | The destination is not on the allowlist. |
| OverCap(remaining) | Amount is above what is left of today's cap. |
| InsufficientBalance(balance) | The leash cannot cover amount plus fee. |
| ZeroAmount() | Amount was 0. |
| SendFailed() | The destination refused the ETH. Nothing changed. |
Agents that act on their own should treat a revert as a "no" from the owner and stop retrying, not look for another route.
Select the leash by id, never by label. Anyone can open a leash naming your agent's address with a copied label, and memos in the feed can be phishing text. If you read leashesOfAgent(agent), keep only ids whose owner is the human you work for.
(03) Limits
What the contract enforces.
| Daily cap | Sum of amount per UTC calendar day (block.timestamp / 1 days). Resets at 00:00 UTC. The fee is not counted. setCap applies at once against today's total; cap 0 works as a soft stop. |
|---|---|
| Midnight | Because the window is a calendar day, up to 2× the cap can go out around midnight UTC (a full cap at 23:59, another at 00:00). Size the cap for that. |
| Allowlist | 1 to 20 addresses at open, no duplicates, not the zero address or the vault. disallow may empty it later; then nothing can be spent. |
| Transfer | Plain ETH with no calldata. The agent can pay an address but cannot call contract functions or move tokens through the leash. An allowlisted contract can still forward ETH anywhere, so choose destinations with care. |
| Stop | stop(id) blocks every spend from the next transaction on, even in the same block. resume(id) undoes it. |
| Withdraw | Leash owner only, any time, also while stopped. ETH always goes to the owner's own address. A leash cannot be transferred to another owner. |
| Contract destinations | The vault sends plain ETH. A contract that credits the sender (WETH, deposit or bridge contracts) will credit the vault, and that ETH is lost. Allow wallets, or contracts you know accept plain ETH for you. The console checks for code and warns before you add one. |
| Agent as destination | Allowed, but it lets the agent pay itself up to the cap every day. Do not add the agent's own address unless you mean it. |
| Funding | Anyone can fund(id). Plain ETH sent to the vault without a function call is rejected. |
| Spam | Anyone can open a leash naming any agent address, so leashesOfAgent may list leashes you did not open. The console shows the owner of every leash; trust only owners you know. |
(04) Fees
0.25% on top, or zero for holders.
Each spend pays a fee of 25 basis points, charged on top from the leash balance, so the destination receives exactly amount. The fee rounds down. It is waived when the leash owner (not the agent) holds at least the holder minimum of the Leashwick token, checked live at every spend. Before the token is set, everyone pays the fee.
Fees accrue in the vault as pendingFees. Anyone can call flushFees() to send them to the LeashBurner, and anyone can call buyAndBurn(minOut) there: it buys the token (at most 0.01 ETH per call, 10 minute cooldown) and sends every token to 0x…dEaD. More on the token page.
(05) Reference
Functions, events, addresses.
| Call | Who |
|---|---|
| open(agent, dailyCap, dests[], label) payable → id | Anyone (becomes owner) |
| fund(id) payable | Anyone |
| withdraw(id, amount) | Owner |
| stop(id) · resume(id) | Owner |
| setCap(id, cap) · allow(id, dest) · disallow(id, dest) | Owner |
| spend(id, to, amount, memo) | Agent |
| flushFees() | Anyone |
| leash · allowlist · isAllowed · remainingToday · maxSpendNow · feeFor · feeWaived · leashesOf · leashesOfAgent · today | Views |
| Receipt(id, agent, to, amount, fee, memo, dayIndex, spentToday) | Event, one per spend |
| Contract | Address (network) |
|---|---|
| LeashVault | not deployed yet |
| LeashBurner | not deployed yet |
| LeashSwapper | not deployed yet |
| RPC | |
| Explorer |
(06) Not audited
What has not been checked by anyone else.
- No audit. The contracts have unit, fuzz, invariant and fork tests, but no independent audit or review. Keep balances small.
- A leaked agent key can send up to the daily cap per UTC day to allowlisted addresses until you call stop. Caps reset at 00:00 UTC, so up to 2× the cap can move around midnight. Press Stop first, then withdraw.
- Spam: anyone can open leashes naming any agent, with any label or memo. The site shows labels and memos as plain text; trust the owner address, not the words.
- The fee waiver is a live balance check. An owner could hold the minimum just for a spend; the cost is at most the 0.25% fee on that spend.
- Burner risks: if the token pool never appears or the token is never set, fees sent to the burner stay there. Leash balances are not affected.
- ETH force-sent to the vault (selfdestruct) belongs to no leash and is stuck.
- No admin can help. There is no proxy, pause, rescue or upgrade. That protects your funds from an admin, and also means nobody can undo a mistake.