To let an AI agent transact today, you give it a private key. A private key has no ceiling. If the agent is prompt-injected, hallucinates a destination, or the key leaks out of a config file, everything in that wallet is gone, and nothing on-chain was in a position to stop it.
The usual answer is a server in the middle that decides which transactions to sign. That works, and it moves the problem. Now you trust the server, and whoever runs it can sign whatever it likes.
BVCC puts the limits in the contract instead. A leaked agent key is worth its remaining budget, not the account.
Most work on agent wallets stops at a spending cap. The harder problem is that a cap says nothing about intent. An agent authorized to swap on Uniswap with a $500 budget can route that swap so the output lands in an attacker's address, and it never goes over $500.
So the wallet inspects the call. For a swap through Uniswap's Universal Router it pins the
recipient argument to your own wallet and matches the command bytes exactly. Anything else
reverts with PinnedArgMismatch(). The agent can trade. It cannot trade on someone
else's behalf. There are 34 adversarial tests and 42 validator tests behind that check.
Supply, borrow, repay, withdraw. Plus four planners that unwind a live position: deleverage, close, swap the collateral, swap the debt — each respecting a health-factor floor and aborting on oracle deviation.
Open a position at a chosen range, collect fees, reduce, close. v4 native ETH pools included, with hooks gated by a registry on a 48-hour timelock.
Uniswap v3 and v4, native ETH in and out, ERC-20 and native sends, approvals.
Most writes have a matching dry-run returning gas and the revert reason, so a model can check whether something works before spending. Four guides it can read first.
Drop the flag and the same server exposes all 53 tools. Any MCP client works: Claude, Cursor, LM Studio, Hermes. Every call still has to pass the contract.
BVCC Agent Wallet
Media kit · reference
| Critical | 2 both fixed |
| High | 3 1 open |
| Medium | 5 3 fixed |
| Low | 1 fixed |
| Informational | 2 |
PinnedArgMismatch().