Skip to main content
This page explains how the agent vault caps daily spending and limits who the agent can pay, how to test both, and how to read the limit from your app.
Everything on this page uses testnet (chain 968). Get free test tokens from the faucet.

What you’ll build

  • An understanding of the two checks in AgentVault.pay: the daily limit and the recipient allowlist.
  • Foundry tests that move time forward to prove the limit resets at 00:00 UTC.
  • vault-status.ts, a script that shows the limit, what’s spent and when it resets.

Prerequisites

  • The AgentVault contract and tests from Agent vaults.
  • A deployed vault, for the last step.

Steps

1

Choose the limit in token units

The vault stores the limit in the token’s smallest unit. USDT on BOT Chain has 6 decimals, so 1 USDT is 1000000. Converting by hand is error prone, so let a tool do it:
The first prints 5, the second prints 5000000. In TypeScript, use parseUnits("5", 6) and formatUnits(value, 6) from viem. For more on decimals, see USDT and decimals.
2

Understand the daily window

The vault counts spending per UTC day. today() divides the block timestamp by 86,400 seconds, so the number changes at 00:00 UTC.
src/AgentVault.sol
It keeps only two numbers: the day it last spent on, and how much it spent that day. When a payment arrives on a new day, the counter starts again from 0. There’s no job that resets it at midnight.remaining is computed with a check instead of plain subtraction. If the owner lowers the limit below what’s already spent today, remaining is 0 instead of the call reverting with an underflow.
A calendar day is simple and cheap, but it allows up to twice the limit in a short span: the full limit at 23:59 UTC and again at 00:00 UTC. If that matters, set the limit to half of what you’re willing to lose in one burst, or use a rolling 24 hour window, which needs more storage per payment.
3

Understand the allowlist

The allowlist is a mapping the owner edits. pay checks it before it touches the limit, so a payment to an unknown address fails even if it’s tiny.
src/AgentVault.sol
The allowlist is the stronger of the two checks. A daily limit caps how much a bad decision costs. An allowlist means the money can only go to places you chose. Prompt injection usually works by getting the agent to pay the attacker, and the allowlist blocks that outright.Every change emits RecipientAllowed, so you can rebuild the current list from the vault’s logs on BOTScan.
4

Test the limit across midnight

Foundry’s vm.warp sets the block timestamp, so you can test the reset without waiting a day. These tests from the agent vault suite cover the limit and the allowlist:
test/AgentVault.t.sol
The vault in these tests has a 10 USDT limit. Run them:
5

Read the limit from your app

Your agent’s tools should check remainingToday() before they try to pay, so the model gets a clear answer instead of a failed transaction. Add VAULT to your bot-defi .env, then save:
vault-status.ts
The reset time comes from the latest block’s timestamp, not your computer’s clock, because that’s what the contract uses.

Verify it worked

The four tests pass:
Output
For a vault with a 0.01 USDT limit that has paid 0.006 USDT today, vault-status.ts prints:
Output

Troubleshooting

The vault uses UTC. Midnight where you are is a different moment unless you’re on UTC. The Resets at line shows the exact time.
Check dailyLimit(). A limit of 0 blocks every payment, and a limit set without decimals, like 5 instead of 5000000, allows only 0.000005 USDT.
The new timestamp is still on the same UTC day. Warp to the start of the next day with (block.timestamp / 1 days + 1) * 1 days, as test_LimitResetsAtUtcMidnight does.
Only the owner can add it, with setRecipientAllowed. That’s the point: the agent can ask, but a person decides. See Human approval for asking in the flow instead.

Next steps

Tool calling

Give a model tools that respect these limits.

Identity hooks

Add a trust check on recipients.
Last modified on October 2, 2026