Skip to content
This repository has been archived by the owner on Jul 5, 2021. It is now read-only.

[WIP] [iOS] Contract Signatures #1067

Open
DmitryBespalov opened this issue Aug 12, 2019 · 0 comments
Open

[WIP] [iOS] Contract Signatures #1067

DmitryBespalov opened this issue Aug 12, 2019 · 0 comments
Labels
Epic feature New feature or request

Comments

@DmitryBespalov
Copy link
Contributor

DmitryBespalov commented Aug 12, 2019

Epic

5afe/safe#78

Documentation

Example Code

Flows

Dapp -> Extension -> App

  1. Dapp is using the Authenticator to ask wallet_signTypedData.
  2. The extension publishes "signTypedData" extension to the app
  3. App displays the "Signature Request" screen
  4. User taps "Sign" button
  5. App publishes the "signTypedDataConfirmation" notification to the extension
  6. Extension creates the contract signature according to our Safe Smart Contract specification
  7. Extension returns the result to the dapp.

Alternative:

  1. User taps "Cancel" button.
  2. App publishes "rejectSignTypedData" notification
  3. Extension cancels the process (cancellation if any of the owners rejected) [CLARIFY]
  4. Extension returns error to the dapp.

Dapp --[WalletConnect]--> App -> Extension

  1. Dapp is using wallet connect to ask wallet_signTypedData
  2. App displays Signature Request" screen.
  3. App publishes the "signTypedData" notification and waits
  4. Extension signs the data (confirmed by user) and publishes the "signTypedDataConfirmation" notification
  5. App collects the signature from the extension.
  6. User taps "Sign" button to sign by the device
  7. App creates the Gnosis Safe Contract signature according to the specification.
  8. App returns the signature as a result of the wallet connect call.

Alternative 1:
4. User taps "Cancel" in the app
5. App publishes "rejectSignTypedData" to the extension
6. App returns error to the wallet connect request result

Alternative 2:
4. User rejects the signing in the extension.
5. Extension publishes "rejectSignTypedData"
6. App receives the rejection and updates the "Signature Request" screen.
7. User can tap "Resend" to send the signature request again.
8. Otherwise, user taps "Cancel" and the app returns error to the wallet connect request.

Data Definition

Push Notifications

Requesting to sign a message

signTypedData

  • payload - message to sign (bytes), hex byte string starting with 0x
  • safe - safe address, should be checksummed?
  • type - signTypedData
  • r - big int, stringified base 10
  • s - big int, stringified base 10
  • v - int, stringified

The sender of the notification shall create an ecdsa signature by:

(r, s, v) = ecdsa_sign(sender_key, keccak(encodeEIP712(payload)))

Then use it to construct the push notification and publish it.

The receiver of the notification must construct the hash of the eip712-encoded payload and recover the origin from the signature and hash. The recovered origin address must be a legitimate owner of the safe otherwise, the message shall be discarded.

Confirming

signTypedDataConfirmation

  • hash: hexadecimal bytestring (0xabc...) - 32 bytes
  • type: signTypedDataConfirmation
  • signature: hexadecimal bytestring (0xabc...) - 129 bytes (64 for 'r', 64 for 's', and 1 for 'v')

The sender of the notification shall create an ecdsa signature in the same way as for the signTypedData notification.

signature = ecdsa_sign(sender_key, keccak(encodeEIP712(payload)))

The receiver of the notification shall check (1) that the hash is an appropriate hash - the one for which the signing request notification signTypedData was published; (2) that the recovered address from the signature is an owner of the safe associated with the signing request.

When there are enough signatures collected (collector's signature + confirmationCount - 1), then the final contract signature is constructed by sorting signatures by their hex (non-checksummed) addresses lexicographically, and concatenating all of them into byte string.

The resulting byte string is the contract signature.

After creating the contract signature, the collector shall check it is valid by calling smart contract's isValidSignature() method. If the signature validation fails, then error shall be shown to the user.

Rejecting

rejectSignTypedData

  • hash: 32-byte string encoding as hexadecimal and starting with '0x'
  • type: rejectSignTypedData
  • r: big int, stringified base 10
  • s: big int, stringified base 10
  • v: big int, stringified base 10

The sender must send this notification when the user rejects the signature signing. This will abort the signing process and return "error" esult to the caller of the signTypedData method.

The sender of the notification creates the (r, s, v) the same way as in the signTypedDataConfirmation with the difference that the signature is serialized with r, s, and v values explicitly rather than in byte string.

(r, s, v) = ecdsa_sign(sender_key, keccak(encodeEIP712(payload)))

The receiver of the notification must check that the signature is valid, that the hash is the one for which signTypedData notification was issued before (pending signature request), and that the signer's address is an owner of the safe associated with the signing request.

WalletConnect RPC

During the development, for testing purposes, the app shall implement the eth_signTypedData with return value that is our contract's signature, instead of the standard ecdsa signature expected by the standard.

In addition, the app shall implement the wallet_signTypedData method to spearhead the extension to the EIP-712 standard. This method shall return signatures only for the * and eip1271 signature types. The ecdsa signature type is not supported by the smart contract.

Contract Signature

Currently, the Safe SC (smart contract) defines the signature as a concatenation of owner signatures, sorted by hex owner address lexicographically.

At the same time, a valid EIP-712 signature is just one signature (r, s, v) parameters that form 129 byte string. Thus, the safe's signature is not a valid EIP-712 signature. For this purpose, Richard has started draft for EIP that would extend the EIP-712 with custom RPC request wallet_signTypedData:

https://github.com/rmeissner/EIPs/blob/rmeissner-wallet-rpc/EIPS/eip-xxx.md#wallet_signtypeddata

There are other custom requests defined in that document.

SafeMessage:

  • is a EIP712 data type wrapper for signing messsages. Safe contract-specific.
  • message of type bytes

EIP712Domain

  • Safe's EIP 712 domain
  • verifyingContract of type address
@DmitryBespalov DmitryBespalov added Epic feature New feature or request labels Aug 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Epic feature New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant