{
  "$schema": "https://hookforge.pages.dev/schema/hook-manifest.json",
  "slug": "agent-budget",
  "name": "AgentBudget",
  "contract": "AgentBudgetHook",
  "version": "1.0.0",
  "family": "Agent-native",
  "summary": "A spending limit the venue itself enforces: an autonomous agent may swap on this pool only within a budget its principal signed, and the pool refuses the swap that would exceed it.",
  "description": "Handing a key to an autonomous agent means choosing between two bad options. Approve a router for a small amount and the agent stalls the moment it needs more, at which point somebody has to be awake to raise it. Approve it for the usual unbounded amount and the only thing standing between a bug and the whole balance is the agent's own code, which is the thing you were trying not to trust. Smart accounts answer this with a policy engine, which works and costs you a smart account: a migration, a new address, a new set of integrations, and a policy layer that every venue has to be taught about. This hook puts the limit somewhere neither of those touch, in the pool, where it applies to any wallet, any router and any account type, because it is enforced by the venue rather than by the spender. A principal signs one `Delegation`, off-chain and once: an agent address, a per-epoch cap in each of the pool's two currencies, an epoch length, an expiry. The agent then signs each swap it makes under that delegation. On `afterSwap` the hook checks both signatures, measures what the swap actually spent from the balance delta, and reverts if that would take the agent past its cap for the current epoch. A revert in `afterSwap` unwinds the swap with it, so an over-budget trade cannot land. Measuring in `afterSwap` rather than `beforeSwap` is deliberate and is what makes the cap honest. Before the swap the only figure available is `amountSpecified`, which on an exact-output swap says nothing about how much the swapper will actually pay; a budget checked against it would be trivially evaded by asking for an exact output and letting the input land wherever the curve puts it. After the swap the true spend is in the delta. What this does not do, stated plainly, because the distinction matters: it never custodies funds, never moves a token, and grants no allowance. The agent still needs its own ERC-20 approval to trade at all. The hook only refuses to let this pool be the venue for a swap outside the budget. An agent with an unbounded approval can still spend elsewhere, so this is a limit on a venue, not on a key, and it is worth exactly as much as the set of venues that enforce it. Both signatures are checked with ERC-1271 as well as ECDSA, so a principal or an agent may itself be a contract.",
  "priorArt": "Per-agent policy engines exist in smart-account land (session keys, ERC-7710 delegations, module-based spending limits), and hooks that gate swaps on an allowlist or a credential are common. Enforcing a signed, per-epoch, per-currency spending cap inside the AMM, on behalf of an EOA principal with no smart account anywhere in the path, is the contribution here.",
  "limitation": "The cap binds this pool only. An agent holding an unbounded ERC-20 approval can spend the same funds on any venue that does not enforce the delegation, so this raises the cost of a compromised agent rather than bounding it absolutely. It also requires the caller to pass hookData, so an aggregator that strips it will simply be unable to trade the pool.",
  "tags": [
    "agent",
    "delegation",
    "spending-limit",
    "eip712",
    "no-admin"
  ],
  "recommendedChains": [
    "base",
    "arbitrum",
    "unichain",
    "robinhood",
    "ethereum",
    "optimism",
    "polygon",
    "bnb"
  ],
  "source": "contracts/src/hooks/AgentBudgetHook.sol",
  "docs": "https://hookforge.pages.dev/hooks/agent-budget",
  "repo": "https://github.com/nirholas/agent-budget",
  "site": "https://agent-budget.pages.dev",
  "permissions": {
    "afterRemoveLiquidityReturnsDelta": false,
    "afterAddLiquidityReturnsDelta": false,
    "afterSwapReturnsDelta": false,
    "beforeSwapReturnsDelta": false,
    "afterDonate": false,
    "beforeDonate": false,
    "afterSwap": true,
    "beforeSwap": false,
    "afterRemoveLiquidity": false,
    "beforeRemoveLiquidity": false,
    "afterAddLiquidity": false,
    "beforeAddLiquidity": false,
    "afterInitialize": false,
    "beforeInitialize": false
  },
  "permissionsSource": "declaration",
  "properties": {
    "dynamicFee": false,
    "upgradeable": false,
    "requiresCustomSwapData": true,
    "vanillaSwap": true,
    "swapAccess": "none"
  },
  "configure": null,
  "errors": [
    {
      "signature": "AuthorizationRequired()",
      "notice": "The swap carried no `hookData`, so there was no delegation to check it against."
    },
    {
      "signature": "BadAgentSignature()",
      "notice": "The swap signature does not recover to the delegation's agent."
    },
    {
      "signature": "BadPrincipalSignature()",
      "notice": "The delegation signature does not recover to the named principal."
    },
    {
      "signature": "BudgetExceeded(uint8,uint128,uint256)",
      "notice": "The swap would take the agent past its budget for the epoch in progress."
    },
    {
      "signature": "Expired()",
      "notice": "The delegation has expired, or the swap authorisation has."
    },
    {
      "signature": "HookNotImplemented()",
      "notice": "The hook function is not implemented."
    },
    {
      "signature": "InvalidEpochLength()",
      "notice": "`epochLength` of zero would make every swap its own epoch, which is no budget at all."
    },
    {
      "signature": "InvalidPool()",
      "notice": "The pool is not configured to use this hook."
    },
    {
      "signature": "NonceAlreadyUsed(uint256)",
      "notice": "This nonce has already been spent under this delegation."
    },
    {
      "signature": "Revoked()",
      "notice": "The principal has revoked this delegation."
    },
    {
      "signature": "WrongPool()",
      "notice": "The delegation is for a different pool than the one being swapped."
    }
  ],
  "deployments": [],
  "abi": [
    {
      "type": "constructor",
      "inputs": [
        {
          "name": "_poolManager",
          "type": "address",
          "internalType": "contract IPoolManager"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "afterAddLiquidity",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct ModifyLiquidityParams",
          "components": [
            {
              "name": "tickLower",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "tickUpper",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "liquidityDelta",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        },
        {
          "name": "delta0",
          "type": "int256",
          "internalType": "BalanceDelta"
        },
        {
          "name": "delta1",
          "type": "int256",
          "internalType": "BalanceDelta"
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        },
        {
          "name": "",
          "type": "int256",
          "internalType": "BalanceDelta"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "afterDonate",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "amount0",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "amount1",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "afterInitialize",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "sqrtPriceX96",
          "type": "uint160",
          "internalType": "uint160"
        },
        {
          "name": "tick",
          "type": "int24",
          "internalType": "int24"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "afterRemoveLiquidity",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct ModifyLiquidityParams",
          "components": [
            {
              "name": "tickLower",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "tickUpper",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "liquidityDelta",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        },
        {
          "name": "delta0",
          "type": "int256",
          "internalType": "BalanceDelta"
        },
        {
          "name": "delta1",
          "type": "int256",
          "internalType": "BalanceDelta"
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        },
        {
          "name": "",
          "type": "int256",
          "internalType": "BalanceDelta"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "afterSwap",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct SwapParams",
          "components": [
            {
              "name": "zeroForOne",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "amountSpecified",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "sqrtPriceLimitX96",
              "type": "uint160",
              "internalType": "uint160"
            }
          ]
        },
        {
          "name": "delta",
          "type": "int256",
          "internalType": "BalanceDelta"
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        },
        {
          "name": "",
          "type": "int128",
          "internalType": "int128"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "beforeAddLiquidity",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct ModifyLiquidityParams",
          "components": [
            {
              "name": "tickLower",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "tickUpper",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "liquidityDelta",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "beforeDonate",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "amount0",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "amount1",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "beforeInitialize",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "sqrtPriceX96",
          "type": "uint160",
          "internalType": "uint160"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "beforeRemoveLiquidity",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct ModifyLiquidityParams",
          "components": [
            {
              "name": "tickLower",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "tickUpper",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "liquidityDelta",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "beforeSwap",
      "inputs": [
        {
          "name": "sender",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "key",
          "type": "tuple",
          "internalType": "struct PoolKey",
          "components": [
            {
              "name": "currency0",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "currency1",
              "type": "address",
              "internalType": "Currency"
            },
            {
              "name": "fee",
              "type": "uint24",
              "internalType": "uint24"
            },
            {
              "name": "tickSpacing",
              "type": "int24",
              "internalType": "int24"
            },
            {
              "name": "hooks",
              "type": "address",
              "internalType": "contract IHooks"
            }
          ]
        },
        {
          "name": "params",
          "type": "tuple",
          "internalType": "struct SwapParams",
          "components": [
            {
              "name": "zeroForOne",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "amountSpecified",
              "type": "int256",
              "internalType": "int256"
            },
            {
              "name": "sqrtPriceLimitX96",
              "type": "uint160",
              "internalType": "uint160"
            }
          ]
        },
        {
          "name": "hookData",
          "type": "bytes",
          "internalType": "bytes"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes4",
          "internalType": "bytes4"
        },
        {
          "name": "",
          "type": "int256",
          "internalType": "BeforeSwapDelta"
        },
        {
          "name": "",
          "type": "uint24",
          "internalType": "uint24"
        }
      ],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "delegationDigest",
      "inputs": [
        {
          "name": "delegation",
          "type": "tuple",
          "internalType": "struct AgentBudgetHook.Delegation",
          "components": [
            {
              "name": "principal",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "agent",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "poolId",
              "type": "bytes32",
              "internalType": "PoolId"
            },
            {
              "name": "cap0",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "cap1",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "epochLength",
              "type": "uint32",
              "internalType": "uint32"
            },
            {
              "name": "expiry",
              "type": "uint64",
              "internalType": "uint64"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "eip712Domain",
      "inputs": [],
      "outputs": [
        {
          "name": "fields",
          "type": "bytes1",
          "internalType": "bytes1"
        },
        {
          "name": "name",
          "type": "string",
          "internalType": "string"
        },
        {
          "name": "version",
          "type": "string",
          "internalType": "string"
        },
        {
          "name": "chainId",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "verifyingContract",
          "type": "address",
          "internalType": "address"
        },
        {
          "name": "salt",
          "type": "bytes32",
          "internalType": "bytes32"
        },
        {
          "name": "extensions",
          "type": "uint256[]",
          "internalType": "uint256[]"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "getHookPermissions",
      "inputs": [],
      "outputs": [
        {
          "name": "",
          "type": "tuple",
          "internalType": "struct Hooks.Permissions",
          "components": [
            {
              "name": "beforeInitialize",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterInitialize",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "beforeAddLiquidity",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterAddLiquidity",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "beforeRemoveLiquidity",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterRemoveLiquidity",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "beforeSwap",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterSwap",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "beforeDonate",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterDonate",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "beforeSwapReturnDelta",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterSwapReturnDelta",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterAddLiquidityReturnDelta",
              "type": "bool",
              "internalType": "bool"
            },
            {
              "name": "afterRemoveLiquidityReturnDelta",
              "type": "bool",
              "internalType": "bool"
            }
          ]
        }
      ],
      "stateMutability": "pure"
    },
    {
      "type": "function",
      "name": "hashDelegation",
      "inputs": [
        {
          "name": "delegation",
          "type": "tuple",
          "internalType": "struct AgentBudgetHook.Delegation",
          "components": [
            {
              "name": "principal",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "agent",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "poolId",
              "type": "bytes32",
              "internalType": "PoolId"
            },
            {
              "name": "cap0",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "cap1",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "epochLength",
              "type": "uint32",
              "internalType": "uint32"
            },
            {
              "name": "expiry",
              "type": "uint64",
              "internalType": "uint64"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        }
      ],
      "stateMutability": "pure"
    },
    {
      "type": "function",
      "name": "hookName",
      "inputs": [],
      "outputs": [
        {
          "name": "",
          "type": "string",
          "internalType": "string"
        }
      ],
      "stateMutability": "pure"
    },
    {
      "type": "function",
      "name": "hookTags",
      "inputs": [],
      "outputs": [
        {
          "name": "tags",
          "type": "string[]",
          "internalType": "string[]"
        }
      ],
      "stateMutability": "pure"
    },
    {
      "type": "function",
      "name": "hookVersion",
      "inputs": [],
      "outputs": [
        {
          "name": "",
          "type": "string",
          "internalType": "string"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "nonceUsed",
      "inputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        },
        {
          "name": "",
          "type": "uint256",
          "internalType": "uint256"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bool",
          "internalType": "bool"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "poolManager",
      "inputs": [],
      "outputs": [
        {
          "name": "",
          "type": "address",
          "internalType": "contract IPoolManager"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "remainingBudget",
      "inputs": [
        {
          "name": "delegation",
          "type": "tuple",
          "internalType": "struct AgentBudgetHook.Delegation",
          "components": [
            {
              "name": "principal",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "agent",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "poolId",
              "type": "bytes32",
              "internalType": "PoolId"
            },
            {
              "name": "cap0",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "cap1",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "epochLength",
              "type": "uint32",
              "internalType": "uint32"
            },
            {
              "name": "expiry",
              "type": "uint64",
              "internalType": "uint64"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "remaining0",
          "type": "uint256",
          "internalType": "uint256"
        },
        {
          "name": "remaining1",
          "type": "uint256",
          "internalType": "uint256"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "revoke",
      "inputs": [
        {
          "name": "delegation",
          "type": "tuple",
          "internalType": "struct AgentBudgetHook.Delegation",
          "components": [
            {
              "name": "principal",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "agent",
              "type": "address",
              "internalType": "address"
            },
            {
              "name": "poolId",
              "type": "bytes32",
              "internalType": "PoolId"
            },
            {
              "name": "cap0",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "cap1",
              "type": "uint128",
              "internalType": "uint128"
            },
            {
              "name": "epochLength",
              "type": "uint32",
              "internalType": "uint32"
            },
            {
              "name": "expiry",
              "type": "uint64",
              "internalType": "uint64"
            },
            {
              "name": "salt",
              "type": "bytes32",
              "internalType": "bytes32"
            }
          ]
        }
      ],
      "outputs": [],
      "stateMutability": "nonpayable"
    },
    {
      "type": "function",
      "name": "revoked",
      "inputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bool",
          "internalType": "bool"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "specURI",
      "inputs": [],
      "outputs": [
        {
          "name": "",
          "type": "string",
          "internalType": "string"
        }
      ],
      "stateMutability": "pure"
    },
    {
      "type": "function",
      "name": "supportsInterface",
      "inputs": [
        {
          "name": "interfaceId",
          "type": "bytes4",
          "internalType": "bytes4"
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bool",
          "internalType": "bool"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "swapDigest",
      "inputs": [
        {
          "name": "authorization",
          "type": "tuple",
          "internalType": "struct AgentBudgetHook.SwapAuthorization",
          "components": [
            {
              "name": "delegationHash",
              "type": "bytes32",
              "internalType": "bytes32"
            },
            {
              "name": "nonce",
              "type": "uint256",
              "internalType": "uint256"
            },
            {
              "name": "deadline",
              "type": "uint64",
              "internalType": "uint64"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "function",
      "name": "usageOf",
      "inputs": [
        {
          "name": "",
          "type": "bytes32",
          "internalType": "bytes32"
        }
      ],
      "outputs": [
        {
          "name": "epochStart",
          "type": "uint64",
          "internalType": "uint64"
        },
        {
          "name": "spent0",
          "type": "uint128",
          "internalType": "uint128"
        },
        {
          "name": "spent1",
          "type": "uint128",
          "internalType": "uint128"
        }
      ],
      "stateMutability": "view"
    },
    {
      "type": "event",
      "name": "BudgetSpent",
      "inputs": [
        {
          "name": "delegationHash",
          "type": "bytes32",
          "indexed": true,
          "internalType": "bytes32"
        },
        {
          "name": "agent",
          "type": "address",
          "indexed": true,
          "internalType": "address"
        },
        {
          "name": "spent0",
          "type": "uint128",
          "indexed": false,
          "internalType": "uint128"
        },
        {
          "name": "spent1",
          "type": "uint128",
          "indexed": false,
          "internalType": "uint128"
        },
        {
          "name": "epochStart",
          "type": "uint64",
          "indexed": false,
          "internalType": "uint64"
        }
      ],
      "anonymous": false
    },
    {
      "type": "event",
      "name": "DelegationRevoked",
      "inputs": [
        {
          "name": "delegationHash",
          "type": "bytes32",
          "indexed": true,
          "internalType": "bytes32"
        },
        {
          "name": "principal",
          "type": "address",
          "indexed": true,
          "internalType": "address"
        }
      ],
      "anonymous": false
    },
    {
      "type": "event",
      "name": "EIP712DomainChanged",
      "inputs": [],
      "anonymous": false
    },
    {
      "type": "error",
      "name": "AuthorizationRequired",
      "inputs": []
    },
    {
      "type": "error",
      "name": "BadAgentSignature",
      "inputs": []
    },
    {
      "type": "error",
      "name": "BadPrincipalSignature",
      "inputs": []
    },
    {
      "type": "error",
      "name": "BudgetExceeded",
      "inputs": [
        {
          "name": "currency",
          "type": "uint8",
          "internalType": "uint8"
        },
        {
          "name": "cap",
          "type": "uint128",
          "internalType": "uint128"
        },
        {
          "name": "wouldSpend",
          "type": "uint256",
          "internalType": "uint256"
        }
      ]
    },
    {
      "type": "error",
      "name": "Expired",
      "inputs": []
    },
    {
      "type": "error",
      "name": "HookNotImplemented",
      "inputs": []
    },
    {
      "type": "error",
      "name": "InvalidEpochLength",
      "inputs": []
    },
    {
      "type": "error",
      "name": "InvalidPool",
      "inputs": []
    },
    {
      "type": "error",
      "name": "InvalidShortString",
      "inputs": []
    },
    {
      "type": "error",
      "name": "NonceAlreadyUsed",
      "inputs": [
        {
          "name": "nonce",
          "type": "uint256",
          "internalType": "uint256"
        }
      ]
    },
    {
      "type": "error",
      "name": "NotPoolManager",
      "inputs": []
    },
    {
      "type": "error",
      "name": "Revoked",
      "inputs": []
    },
    {
      "type": "error",
      "name": "StringTooLong",
      "inputs": [
        {
          "name": "str",
          "type": "string",
          "internalType": "string"
        }
      ]
    },
    {
      "type": "error",
      "name": "WrongPool",
      "inputs": []
    }
  ]
}
