> 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/reference/eip712.md).

# EIP-712 typed data

Every signed operation in Sail is EIP-712 typed data. This page lists the exact type strings the kernel verifies (from `SailKernel`), plus the template `Configure` type from `BaseSharedPermission`. All type hashes are `keccak256` of the type string shown.

{% hint style="warning" %}
These are the **current, selective-model** type strings. They differ from older revisions: `Dispatch` now carries a `permission` field, and every registry operation carries a `deadline`. Always read the kernel's public `*_TYPEHASH` constants (or `DISPATCH_TYPEHASH()`) on-chain rather than hardcoding — the Sailor SDK detects them for you.
{% endhint %}

## Domain

```
EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)
  name              = "SailKernel"
  version           = "1"
  chainId           = <the chain>
  verifyingContract = <the SailKernel address>
```

`kernel.hashTypedDataV4(structHash)` applies this domain on-chain; equivalently `keccak256("\x19\x01" ++ domainSeparator ++ structHash)`.

## Manager operations (signed by `manager`)

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

* `dataHash = keccak256(data)`; `nonce = managerNonces[account]`.
* `callsHash = keccak256(abi.encode(calls))`; `nonce = batchNonces[account]`.

## Permission-signer operations (signed by `permissionSigner`)

```
RegisterPermission(address account,address permission,uint256 nonce,uint256 deadline)
RevokePermission(address account,address permission,uint256 nonce,uint256 deadline)
ReplacePermission(address account,address oldPermission,address newPermission,uint256 nonce,uint256 deadline)
RegisterPermissions(address account,address[] permissions,uint256 nonce,uint256 deadline)
RevokePermissions(address account,address[] permissions,uint256 nonce,uint256 deadline)
ReplacePermissions(address account,address[] oldPermissions,address[] newPermissions,uint256 nonce,uint256 deadline)
RevokeSession(address account,uint256 nonce,uint256 deadline)
ActivateSession(address account,uint256 nonce,uint256 deadline)
SetFeePolicy(address account,address newFeePolicy,address feeAsset,uint256 nonce,uint256 deadline)
```

All use `nonce = signerNonces[account]`.

## Template configuration (signed by `permissionSigner`, verified by the template)

```
Configure(address account,bytes32 paramsHash,uint256 nonce,uint256 deadline)
SetAgentIdentity(address account,bytes32 identityHash,uint256 nonce,uint256 deadline)
```

* `paramsHash = keccak256(params)`; `nonce = template.configNonces(account)`.
* Verified against the EIP-712 domain of the **template** (each shared template is its own `EIP712` domain, e.g. `name = "SharedBoundedSwapPermission"`, `version = "1"`), not the kernel.

## Encoding `address[]`

For `RegisterPermissions` / `RevokePermissions` / `ReplacePermissions`, an `address[]` field is encoded per EIP-712 §4 as the keccak256 of the ABI-encoded, zero-padded addresses:

```solidity
bytes32 arrHash = keccak256(abi.encodePacked(/* each address as bytes32 */));
```

(The kernel's `_hashAddressArray` builds a `bytes32[]` of zero-padded addresses and hashes the packed result.)

## Building a digest (example: Dispatch)

```solidity
bytes32 structHash = keccak256(abi.encode(
    kernel.DISPATCH_TYPEHASH(),
    account, permission, target, value,
    keccak256(data),
    kernel.managerNonces(account),
    deadline
));
bytes32 digest = kernel.hashTypedDataV4(structHash);
// sign `digest` with the manager key (ECDSA), or have an ERC-1271 signer attest it
```

Signatures are verified with `_recoverOrERC1271`: ECDSA first, then ERC-1271 fallback for contract signers — so managers and permission signers may be EOAs, multisigs, or smart accounts.


---

# 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/reference/eip712.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.
