Contract Reference
Solidity sources live in the contracts/ folder of the monorepo. Built with Foundry + OpenZeppelin, pragma ^0.8.27, via_ir = true.
Deployed addresses
Deterministic CREATE2 — same address on every network:
| Contract | Address |
|---|---|
BVCCSmartWalletFactoryV2 | 0x230b7010529AB6977Dd8581B3eF018ef865BdEf1 |
BVCCAgentWalletFactoryV2 | 0x8D9e24022777173AD6336e00884b6C87c7EF054c |
| EntryPoint (OpenZeppelin v0.9) | 0x433709009B8330FDa32311DF1C2AFA402eD8D009 |
Live on Arbitrum One, Base, BNB Chain, Ethereum, Polygon and Arbitrum Sepolia (testnet) — same addresses on every network.
BVCCSmartWalletV2 — personal wallet (walletType 0)
One contract per user, deployed by the factory. No proxies, no upgradability.
- ●Signer: WebAuthn / P-256 public key (passkey), fixed at deployment. Every
execute()is authenticated via ERC-4337 UserOp signature validation. - ●Execution: ERC-7821 batched execution (
execute(bytes32 mode, bytes executionData)withExecution[]batches). - ●Fee: 0.05% per operation to the BVCC fee wallet (
0x3e3eb089169a7315a994947465ce5f5FC3A307D4), three cases — (1) ETH send: fee deducted from the sent value; (2) ERC-20 transfer: fee charged on top, the wallet must holdamount + fee; (3) DeFi/swap: balance snapshot before/after, fee on detected token balance increases. - ●Recovery: 3 guardian addresses, set once at creation. Replacing the WebAuthn signer requires 2-of-3 guardian signatures + a 48-hour timelock. Recovery functions bypass
execute()and pay no fee.
BVCCAgentWalletV2 — AI agent wallet (walletType 1)
Extends BVCCSmartWalletV2; adds delegated execution for authorized agent EOAs. Fee is 0.15%.
AuthorizeParams (input to authorizeAgent)
| Field | Type | Meaning (`0` = unlimited/disabled) |
|---|---|---|
agent | address | agent EOA (must have no code) |
maxPerTxWei | uint128 | max ETH per single Execution item |
dailyLimitWei | uint128 | max ETH per UTC day |
totalBudgetWei | uint128 | lifetime ETH budget |
periodBudgetWei | uint128 | max ETH per rolling period |
periodDuration | uint64 | period length in seconds |
expiry | uint64 | unix timestamp; agent disabled after |
allowedTokens | address[] | ERC-20 whitelist; empty = deny all token ops |
tokenMaxAmounts | uint128[] | parallel: token cap per batch |
tokenDailyLimits | uint128[] | parallel: token cap per UTC day |
tokenTotalBudgets | uint128[] | parallel: lifetime token budget |
allowedProtocols | address[] | DeFi target whitelist; empty = deny all DeFi calls |
allowedRecipients | address[] | unified destination whitelist (ETH recipients, token recipients, approve spenders); empty = allow any |
Whitelists max 20 entries each. The four token arrays must have equal length.
Owner functions (callable only via the wallet’s own execute(), i.e. biometrics / WebAuthn)
Agent functions
See the Agent Integration Guide for call encoding, validation order and error reference.
Getters
Factories
Both factories share the same shape:
- ●Deterministic address: salt =
keccak256(abi.encode(pubKeyX, pubKeyY))— derived only from the passkey’s P-256 public key. Same key → same wallet address on every network. Guardians don’t affect the address (set post-deploy viasetGuardians, callable once). - ●Counterfactual:
getWalletAddressis a view — you can receive funds at the address before deploying. - ●Idempotent:
createWalletreturns the existing wallet if already deployed. - ●Kill switch:
kill()stops new creations only; existing wallets are independent contracts and keep working with their funds.
Security notes
- ●Internal security review (bilingual report in the monorepo’s
audits/folder): HIGH finding (approve cap-bypass) fixed; 131/131 Foundry tests pass; Slither clean of real findings. - ●V2 (June 2026) fixed a gas-griefing edge on Arbitrum: balance probes are now capped at 100k gas (
PROBE_GAS_CAP) so calldata that happens to contain a precompile address can’t burn the transaction’s gas.
⚠No external audit yet — this is experimental beta software.