# **Ledger Signing Flow Specification for Safe Transactions**
**Purpose:** To define the expected screen-by-screen display on a Ledger hardware wallet when approving a Safe Account transaction with a standard configuration.
## Overview
This document outlines the precise, sequential flow of screens displayed on a Ledger device for a specific signing configuration. For Safe transactions, the Ledger's Ethereum app requires "Blind Signing" to be enabled because it processes the signature as a generic EIP-712 message. The goal of the in-app component is to replicate this exact flow to provide a secure and trustworthy verification experience.
---
### **Recommended Ledger Settings**
TLDR: For an optimal balance of security and UX when signing Safe transactions, we recommend enabling on Ledger Settings both `Transaction Hash Display` and `Debug Contract Data` while keeping `EIP-712 Raw Messages (Verbose)` disabled. This configuration allows to verify a transaction with the `domain hash` and `message hash` without the risk of "review fatigue" from overly verbose displays.
---
#### **Detailed Configuration and Rationale**
Ledger Device: Nano X / S Plus
Firmware: v2.5.0 (latest)
Ethereum-app: v0.18.0 (latest)
**1. Blind Signing: `Enabled`**
* **Rationale:** Required to be enabled to sign any Safe Transactions.
2. **Nonce**: `Enabled` (Irrelevant)
* Rationale: This the signer nonce and not the Safe account nonce.
**3. Raw Messages (EIP-712): `Disabled`**
* **Relevant**: Only during signing.
* **Rationale:** While this mode display every field of the EIP-712 struct, it is impractical and often counter-productive for Safe transactions. A single transaction can expand into dozens of individual screens for the user to approve. This leads to **review fatigue**, a security risk where users begin approving screens without careful verification.
**4. Debug Contract Data: `Enabled`**
* **Relevant**: Only during executing.
* **What it does**: This setting displays the calldata of the transaction on the connected signer interface (e.g., MetaMask).
**Rationale**: Generally speaking, for maximum clarity, we recommend a two-step process: have all owners sign the transaction first, and then have one person send a separate transaction to execute it.
Reviewing a simple signature request on a hardware wallet is far less complex than reviewing the full, raw data of an execution transaction. However, we will still support the combined "sign and execute" flow for users who prioritize gas savings, but it comes at the cost of a less transparent approval process for the final signer.
**5. Smart Accounts (EIP-7702): `Disabled`** (Irrelevant)
* **Rationale:** Safe accounts do not support EIP-7702. This is mainly for upgrading EOAs.
**6. Transaction Hash Display: `Enabled`**
* **Rationale:** This is the key to achieving a high level of verification without compromising usability. When enabled, the Ledger will present the final EIP-712 `domain hash` and `message hash` before signing. This allows a user to verify the two most important elements of the transaction on their trusted device, confirming that the payload has not been tampered with.
---
## Ledger Configuration Comparison
Below are the different combination of configurations that we've evaluated on Ledger to identify the most secure and user-friendly settings for signing transactions.
| Setting / Parameter | Settings A (Recommended) | Settings B |
| :--- | :--- | :--- |
| **Blind Signing** | Enabled | Enabled |
| **Raw Messages (EIP-712)**| Disabled | Enabled |
| **Debug Contract Data** | Enabled | Enabled |
| **Transaction Hash Display**| Enabled | Disabled |
## Ledger Settings A (Recommended)
* **Blind Signing:** `Enabled`
* **Debug Contract Data:** `Enabled`
* **Raw Messages (EIP-712):** `Disabled`
* **Transaction Hash Display:** `Enabled`
---
### Signing Screen-by-Screen Display Flow A
**Step 1: Blind Signing Warning**
The device displays a full-screen warning prompt that the user must accept.
* **Line 1**: `Blind signing ahead`
* **Line 2**: `To accept risk, press`
* **Line 3**: `both buttons`
**Step 2: Action Prompt**
* **Screen Text:** `Review typed message`
**Step 3: Chain ID**
* **Line 1:** `chainId`
* **Line 2:** `1`
**Step 4: Verifying Contract Address**
* **Line 1:** `verifyingContract`
* **Line 2:** `0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2`
**Step 5: Message Hash (Part 1 of 2)**
The first part of the 32-byte message hash is shown. The hash is split across multiple lines on this screen.
* **Line 1:** `Message hash (1/2)`
* **Subsequent lines display chunks of the hash:**
* `0x1e7f9fcc086a5478`
* `70576da303533f9579`
* `7d9b5a82b311bb966`
**Step 6: Message Hash (Part 2 of 2)**
The final part of the message hash is shown on the next screen.
* **Line 1:** `Message hash (2/2)`
* **Subsequent line displays the final chunk:**
* `1a184180de6a4`
**Step 7: Domain Hash Display**
The device displays the full EIP-712 Domain Separator hash, split into two screens.
* **Screen 1/2 Text:**
* **Line 1:** `Domain hash (1/2)`
* **Subsequent lines display chunks of the hash:**
* `0xb5a65c888137bea`
* `ddd0c0d5ecc0eb75`
* `cf59371a0441a6a49`
* **Screen 2/2 Text:**
* **Line 1:** `Domain hash (2/2)`
* **Line 2:** `0e74ce2ac02f9eaa`
**Step 8: Message Hash Display**
* **Line 1:** `Message hash (1/2)`
* **Subsequent lines display chunks of the hash:**
* `0x1e7f9fcc086a5478`
* `70576da303533f9579`
* `7d9b5a82b311bb966`
**Step 9: Message Hash (Part 2 of 2)**
The final part of the message hash is shown on the next screen.
* **Line 1:** `Message hash (2/2)`
* **Subsequent line displays the final chunk:**
* `1a184180de6a4`
**Step 10: Final Approval**
The user is prompted to finalize the signature.
* **Screen Text:** `Accept and send`
---
## Ledger Settings B
* **Blind Signing:** `Enabled`
* **Raw Messages (EIP-712):** `Enabled`
* **Debug Contract Data:** `Disabled`
* **Transaction Hash Display:** `Disabled`
---
### Signing Screen-by-Screen Display Flow
**Step 1: Blind Signing Warning**
The device displays a full-screen warning prompt that the user must accept.
* **Line 1**: `Blind signing ahead`
* **Line 2**: `To accept risk, press`
* **Line 3**: `both buttons`
**Step 2: Action Prompt**
* **Screen Text:** `Review typed message`
**Step 3: Review Struct - EIP712Domain**
The device announces the start of the EIP-712 Domain structure review.
* **Line 1:** `Review struct`
* **Line 2:** `EIP712Domain`
**Step 4: Chain ID**
* **Line 1:** `chainId`
* **Line 2:** `1`
**Step 5: Verifying Contract**
* **Line 1:** `verifyingContract`
* **Line 2:** `0xD9e5DA4006f2d7c`
* **Line 2:** `A96f00BD25bA3742D`
* **Line 3**: `52c33ea5`
**Step 6: Review Struct - SafeTx**
The device announces the start of the primary Safe Transaction message review.
* **Line 1:** `Review struct`
* **Line 2:** `SafeTx`
**Step 7: Recipient Address ("to")**
* **Line 1:** `to`
* **Line 2:** `0xD9e5DA4006f2d7c`
* **Line 2:** `A96f00BD25bA3742D`
* **Line 3**: `52c33ea5`
**Step 8: Value**
The amount of the transaction in Wei.
* **Line 1:** `value`
* **Line 2:** `1000`
**Step 9: Data**
* **Line 1:** `data`
* **Line 2:** `0x`
> This is an ETH tansfer example. For smart contract interaction like ERC-20 tokens transfers or batch transactions, this will be presented into 7+ screens.
**Step 10: Operation**
The type of Safe operation (0 for CALL, 1 for Delegate CALLS).
* **Line 1:** `operation`
* **Line 2:** `0`
**Step 11: Safe Transaction Gas ("safeTxGas")**
* **Line 1:** `safeTxGas`
* **Line 2:** `0`
**Step 12: Base Gas**
* **Line 1:** `baseGas`
* **Line 2:** `0`
**Step 13: Gas Price**
* **Line 1:** `gasPrice`
* **Line 2:** `0`
**Step 14: Gas Token**
The token used for gas payment (zero address for native ETH).
* **Line 1:** `gasToken`
* **Line 2:** `0x00000000000000000`
* **Line 3:** `0000000000000000000`
* **Line 4:** `0000`
**Step 15: Refund Receiver**
* **Line 1:** `refundReceiver`
* **Line 2:** `0x00000000000000000`
* **Line 3:** `0000000000000000000`
* **Line 4:** `0000`
**Step 16: Nonce**
The transaction nonce of the Gnosis Safe.
* **Line 1:** `nonce`
* **Line 2:** `2`
**Step 17: Final Approval**
The final prompt to sign the fully reviewed message.
* **Screen Text:** `Sign message`