### Step-by-Step Guide to Signing and Validating a Message for `COWShed` Execution
1. **Prepare the Message Data to Sign**
- In `COWShed`, the message data includes the following parameters:
- `calls`: An array of `Call` structs, each containing the `target`, `value`, `callData`, `allowFailure`, and `isDelegateCall`.
- `nonce`: A unique identifier for the transaction, preventing replay attacks.
- `deadline`: The timestamp until which the message is valid.
- Using these parameters, the message data to be signed is constructed by `LibAuthenticatedHooks` as follows:
```solidity
bytes32 messageData = keccak256(
abi.encode(
LibAuthenticatedHooks.EXECUTE_HOOKS_TYPE_HASH,
LibAuthenticatedHooks.callsHash(calls),
nonce,
deadline
)
);
```
- This `messageData` is the core data you want the Safe to recognize as valid.
2. **Generate the Domain Separator in `COWShed`**
- `COWShed` provides its own domain separator for EIP-712 compatibility, which includes the contract’s name, version, chain ID, and address:
```solidity
bytes32 domainSeparator = COWShed.domainSeparator();
```
- This domain separator is essential to make the hash specific to `COWShed`.
3. **Create the Full Message Hash for Signing**
- Using the domain separator and `messageData`, we generate the final `msgHash`:
```solidity
bytes32 msgHash = keccak256(
abi.encodePacked(
bytes1(0x19),
bytes1(0x01),
domainSeparator,
messageData
)
);
```
4. **Delegate Call to `SignMessageLib`**
- To mark the `msgHash` as approved by the Safe, perform a `delegatecall` to `SignMessageLib` from within the Safe, calling `SignMessageLib.signMessage` with `_data` as the encoded message data:
```solidity
SignMessageLib(signMessageLibAddress).signMessage(_data);
```
- This ensures that the message is stored as signed in the Safe’s `signedMessages` mapping.
5. **Sign the Message Hash within the Safe**
- When `signMessage` is called, it calculates `msgHash` internally and sets `signedMessages[msgHash] = 1`, marking it as approved.
- An event `SignMsg(bytes32 msgHash)` is emitted, confirming the signing and approval of the message hash.
6. **Execute the Call in `COWShed`**
- Now that the message hash is approved in the Safe’s storage, `COWShed` can execute actions based on it.
- When `COWShed` receives the message for execution, it uses `LibAuthenticatedHooks` to validate the signed message. The `LibAuthenticatedHooks.authenticateHooks` function checks that the Safe’s `signedMessages` mapping contains the `msgHash`.
7. **Validate the Signature with `CompatibilityFallbackHandler`**
- `CompatibilityFallbackHandler` in the Safe validates that `signedMessages[msgHash]` is set.
- This verification confirms the message’s authenticity, allowing `COWShed` to execute the actions specified in the signed message.
---
### Complete Process Summary
1. **Define Message Data:** Include `calls`, `nonce`, and `deadline` for `COWShed` as part of the message data.
2. **Generate Domain Separator and Message Hash:** Combine the domain separator and message data for the full `msgHash`.
3. **Delegate Call to SignMessageLib:** Use `delegatecall` to mark `msgHash` as signed within the Safe’s `signedMessages`.
4. **Approve Message in Safe:** `SignMessageLib` sets `signedMessages[msgHash] = 1` and emits an event.
5. **Execute in COWShed:** With the approved message, `COWShed` performs the intended actions after verifying the signature via the Safe’s `CompatibilityFallbackHandler`.