> For the complete documentation index, see [llms.txt](https://docs.sail.money/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sail.money/protocol/guides/dispatch.md).

# Dispatch a transaction within bounds

With the SMA registered and at least one permission attached, the manager can execute calls. Each dispatch names the one permission that should authorize it.

## 1. Build the Dispatch signature

The selective-model type string (note the `permission` field):

```
Dispatch(address account,address permission,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
```

Sign with the **manager** key:

```
dataHash  = keccak256(data)                  // the call's calldata
structHash = keccak256(abi.encode(
    DISPATCH_TYPEHASH,
    account, permission, target, value, dataHash,
    managerNonces[account],                   // read from the kernel
    deadline
))
digest    = kernel.hashTypedDataV4(structHash)
managerSig = sign(digest, managerKey)         // ECDSA or ERC-1271
```

Read the nonce from `kernel.managerNonces(account)`.

## 2. Submit

```solidity
kernel.dispatch(account, permission, target, value, data, managerSig, deadline);
```

The kernel verifies the signature, staticcalls `permission.evaluate(data, ctx)` under the 150k gas cap, and — only if it returns `true` — executes `execTransactionFromModule(target, value, data, 0)` on the Safe. On success it emits `Dispatched(account, permission, target, selector, value)`.

## What a denial looks like

The dispatch **reverts** (no state change) in these cases:

| Revert                                | Cause                                                                               |
| ------------------------------------- | ----------------------------------------------------------------------------------- |
| `PermissionNotRegistered(permission)` | you named a permission that isn't on the account's mandate                          |
| `PermissionDenied(permission)`        | the permission returned false, reverted, ran out of gas, or returned malformed data |
| `SessionInactive(account)`            | the session is paused (`revokeSession` was called)                                  |
| `DeadlineExpired(deadline, now)`      | `block.timestamp > deadline`                                                        |
| `InvalidManagerSignature()`           | the signature didn't recover to the account's `manager`                             |
| `AccountSelfTarget()`                 | `target == account` (blocked — would let the Safe reconfigure itself)               |
| `SafeExecutionFailed()`               | the permission approved it but the Safe call itself failed                          |
| `ProtocolPaused()`                    | the protocol is paused                                                              |

Because evaluation is fail-closed, a buggy permission denies rather than over-permits. If you hit `PermissionDenied`, re-check the permission's bounds against your call — it's doing its job.

## Nonces and in-flight invalidation

Each successful dispatch increments `managerNonces[account]`. If the Permission Signer revokes a permission, revokes the session, replaces a permission, or the Safe rotates the manager, the kernel bumps the manager-nonce **epoch** (`1 << 128`), which invalidates **every dispatch the manager had pre-signed but not yet submitted**. This means tightening the mandate cannot be raced by a stale signature.

## Batches

For an atomic multi-call sequence (e.g. `approve → call → reset`), use `dispatchBatch` with a batch-aware permission. The signature is over `DispatchBatch(account, permission, callsHash, nonce, deadline)` with `callsHash = keccak256(abi.encode(calls))`, using the separate `batchNonces`. You can pre-check a batch off-chain with `previewBatch(account, permission, calls)`. See [single & batch dispatch](/protocol/architecture/dispatch.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sail.money/protocol/guides/dispatch.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
