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.
Domain
Section titled “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)
Section titled “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)
Section titled “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)
Section titled “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
EIP712domain, e.g.name = "SharedBoundedSwapPermission",version = "1"), not the kernel.
Encoding address[]
Section titled “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:
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)
Section titled “Building a digest (example: Dispatch)”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 itSignatures 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.