A daily spending limit for your AI agent.
The agent is deliberately gullible. The contract isn't.
How it works
- Deposit USDG (or any ERC-20) into a vault on Robinhood Chain, name your agent's address, set a daily cap and a list of allowed recipients.
- The agent can only call
spend(to, amount, memo). Inside the cap and to a listed recipient, the money moves. Anything else is refused by the contract and recorded as aRefusedevent. - Change the cap, swap or revoke the agent, withdraw — any time. Only the vault owner can.
Your agent only needs gas. The money stays in the vault. About 0.001 ETH covers roughly 1,000 spends. Every refusal is a transaction on Robinhood Chain; see /proof.
Works with USDG or any standard ERC-20 on Robinhood Chain, including tokenized stocks. Tokens that charge the sender extra or rebase downward aren't supported.
Numbers
What the contract guarantees vs what the team does
The contract guarantees
- A vault, its daily cap and its allowlist.
- Revoking the agent and withdrawing, by the owner, any time.
- A
Refusedevent for every refused spend, with the reason. - The token has no function in the contract.
The team does, by hand
- The demo agent tries every payment request it is given. That is its system prompt, and you can test it on the home page.
- Paid sinks are swept back into the demo vault by hand. Refills are public transactions. Nothing is promised.
- Creator fees pay for the server, the model and the demo vault's refills.
Contract
Source verified on Sourcify (exact match).
Functions
| Function | Who | What |
|---|---|---|
| createVault(asset, agent, dailyCap, recipients[]) | anyone | New vault, you are the owner. The agent may be empty (zero) and set later, but cannot be you. |
| deposit(id, amount) | anyone | Adds the amount actually received to the vault. Send funds with deposit only: tokens sent directly to the contract can't be recovered. |
| withdraw(id, amount) | owner | Sends the amount back to the owner's own address only. If the token issuer blacklists the owner, the withdraw fails. |
| setAgent(id, agent) | owner | Swap the agent. Zero revokes it. |
| setDailyCap(id, cap) | owner | Change the cap. Zero pauses the agent. |
| setRecipient(id, to, ok) | owner | Allow or remove a recipient. |
| spend(id, to, amount, memo) | agent | Returns true and moves the money, or returns false and emits Refused. It does not revert on refusal. |
| remaining(id) | view | Cap minus spent today. |
| canSpend(id, to, amount) | view | 0 means it would pass; otherwise the reason code below, or 4 when the vault has no agent. |
Events
VaultCreated, Deposited, Withdrawn, AgentSet, CapSet, RecipientSet, Spent, Refused.
Refusal reasons
| Code | Name | Meaning |
|---|---|---|
| 1 | RECIPIENT_NOT_ALLOWED | The recipient is not on the allowlist. |
| 2 | OVER_DAILY_CAP | The amount is more than what is left of today's cap. |
| 3 | INSUFFICIENT_VAULT_BALANCE | The vault holds less than the amount. |
Demo agent
- Model: . Two tools:
spendandremaining. - It is deliberately gullible: it tries every payment request, even obvious traps, and does not pre-check limits. The vault decides.
- Each message is a fresh conversation.
- Server rule, not a contract rule: amounts must be between 0.01 and 1000000 USDG; memos are cut to 64 bytes and links are removed.
- Limits: Agent budget:
- Prompts shown on /proof are filtered and labelled "prompt as typed (server log)".
spend() on vault #1. If it leaked, the most anyone could do is spend what is left of that day's cap, to the three allowed recipients. That is the point of the contract.Transaction status OK does not mean money moved
A refused spend is a successful transaction that moves no tokens. Look for Spent versus Refused in the logs. On Blockscout a refusal shows status OK with no token transfer.
The daily window
The window is the UTC calendar day. It resets at 00:00 UTC. A midnight burst can reach twice the cap across two UTC days: an agent can spend what is left of today, then the next day's cap, within minutes of 00:00 UTC.
For agents
Read how much is left, then pay from the agent key. Amounts are in the asset's smallest unit (USDG has 6 decimals).
cast
curl
viem
spend returns ok: false instead of throwing when the vault refuses; check it. Call canSpend first if you want to know without sending a transaction.
Token
The token is the project's coin on Pons. It does nothing inside the contract. Creator fees pay for the server, the model, and the demo vault's refills — by hand, with public transactions, nothing promised.
FAQ
What happens when my agent asks for too much?
The contract refuses, emits Refused with the reason, and no funds move.
Can I get my money out if the agent misbehaves?
Yes. Only you, as owner, can withdraw, and you can revoke the agent or set the cap to zero at any time.
Which assets work?
USDG, or any standard ERC-20 on Robinhood Chain, including tokenized stocks. One asset per vault. Tokens that charge the sender extra or rebase downward aren't supported.
When does the cap reset?
At 00:00 UTC, every day.
Does my agent need ETH?
Only for gas. The money stays in the vault.
Is the demo agent's key safe?
It lives on our server and can only call spend() on vault #1, which is limited by the contract. See the hot key note above.
Experimental software. Use amounts you can afford to lose. Nothing here is financial advice.