# Extensible `Safe` Architecture This document outlines an *extensible* `Safe` architecture, increasing the novel integrations / applications for `Safe`. The following guiding principles have been **strictly** employed: 1. State for the `SafeProxy` **MUST** not be modified, ensuring maximum security. 2. No use of `delegatecall` within the architecture. ## Use cases Currently, a `safe` may only be interacted with via either: 1. The `owners` via `execTransaction`; or 2. An authorised `module` via `execTransactionFromModule`; or 3. Third parties who wish to verify a `signature` (ERC-1271). Use cases that this revised architecture seeks to enable include: 1. Arbitrary method invocation on the `SafeProxy`. As an example, this would make it theoretically possible to convert a `SafeProxy` into an ERC20 token by implementing ERC20 methods. 2. Authorise a 3rd party contract to verify EIP-712 signatures for a specific domain on behalf of the `Safe`. As an example, one could delegate the CoW Protocol EIP-712 domain to a contract that verified all signatures for selling any ERC20 token to ETH, ie. Max ETH :rocket: ## Current Architecture The execution path of any method call that is _not_ implemented in the `Safe` singleton follows this path: ```mermaid flowchart TD A[SafeProxy] -->|delegatecall| B[Safe - `FallbackManager`] B -->|call| C[CompatibilityFallbackHandler] ``` `CompatibilityFallbackHandler` provides: 1. ERC-1271 signing, using either approved hashes, or threshold signatures. 2. Miscellaneous token callbacks for ERC721 / ERC1155 etc. If a developer wishes to extend the functionality of a `Safe`, they have to replace the `CompatibilityFallbackHandler`, requiring significant heavy lifting, being careful to not remove any existing functionality so as to not break `Safe` (some parts of existing infrastructure require the use of threshold signatures, and some apps are using approved hashes such as CoW Protocol dapp). A developer may *extend* `CompatibilityFallbackHandler`, though it can be made much easier if one could simply specify a custom handler for arbitrary individual methods. This is where `ExtensibleFallbackHandler` comes in. ## `ExtensibleFallbackHandler` This handler replaces `CompatibilityFallbackHandler`, but preserves backwards compatibility with: 1. ERC-1271 `Safe` approved hashes / threshold signatures. 2. Token callbacks. 3. ERC165. In addition to the backwards compatibility, a user may: 1. Specify a handler for a custom method. 2. Specify a set of handlers for custom methods and indicate that the `Safe` now supports an interface. 3. Specify a custom verifier for an EIP-712 domain. ### Custom Methods Security requirements: * The `Safe` **SHALL** determine (based on the authorisation in the setter) whether a custom method is `view` or not (ie. whether or not the custom method can modify state on invocation). Execution Path: ```mermaid flowchart TD A[SafeProxy] -->|delegatecall| B[Safe - `FallbackManager`] B -->|call| C[ExtensibleFallbackHandler] C -->|call| D[IFallbackMethod] C -->|staticcall| E[IStaticFallbackMethod] ``` ### Custom EIP-712 Verifiers User requirements: 1. Custom verifiers **MUST** be able to accept an arbitrary, implementation specific `bytes` payload. Security requirements: * `EIP-712` domain separator **MUST** be checked against the `hash`, ensuring a 1:1 relationship between domain separator and `ISafeSignatureVerifier`. Execution Path for `isValidSignature(bytes32,bytes)`: ```mermaid flowchart TD A[SafeProxy] -->|delegatecall| B[Safe - `FallbackManager`] B -->|call| C[ExtensibleFallbackHandler - `SignatureVerifierMuxer`] C --> D[Approved Hash] C --> E[Threshold Signature] C -->|call| F[ISafeSignatureVerifier] ``` #### Encoding of `signature` * `approvedhash` - `signature` is set to zero-length `bytes`. * `threshold` - `signature` is a multiple of 65 bytes (for `r`, `s`, `v`). * `custom` (ie. `ISafeSignatureVerifier`) - `signature` is an ABI encoded function call `safeSignature(bytes32,bytes32,bytes32,bytes)` where the tuple equates to `(bytes32 domainSeparator, bytes32 typeHash, bytes32 encodeData, bytes payload)`. It is the `4bytes` selector in the ABI encoded function call that is used to trigger the custom signer. #### Custom Verifier Validation Before `SignatureVerifierMuxer` calls a custom verifier, it **MUST** match the `domainSeparator` to the `hash`. Therefore, this then means that `typeHash`, and `encodeData` can be trusted within `ISafeSignatureVerifier` if called from `SignatureVerifierMuxer`. #### `ISafeSignatureVerifier` Security requirements: * An implementation **MAY** reassert `_hash = h(abi.encodePacked("\x19\x01", domainSeparator, h(typeHash || encodeData)))`. ### Storage Storage of custom method handlers and custom domain verifiers is contained within the `ExtensibleFallbackhandler` deployment. Therefore, any update of the `fallbackHandler` for a `Safe` would in-effect "reset" the custom methods / domain verifiers for the `Safe.`