-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
37e596a
commit e33f73d
Showing
4 changed files
with
78 additions
and
0 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
contracts/mocks/docs/utils/cryptography/ERC7739SignerECDSA.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// contracts/ERC7739SignerECDSA.sol | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | ||
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; | ||
|
||
import {ERC7739Signer} from "../../../../utils/cryptography/draft-ERC7739Signer.sol"; | ||
|
||
contract ERC7739SignerECDSA is ERC7739Signer { | ||
address private immutable _signer; | ||
|
||
constructor(address signerAddr) EIP712("ERC7739SignerECDSA", "1") { | ||
_signer = signerAddr; | ||
} | ||
|
||
function _validateSignature(bytes32 hash, bytes calldata signature) internal view virtual override returns (bool) { | ||
(address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); | ||
return _signer == recovered && err == ECDSA.RecoverError.NoError; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
contracts/mocks/docs/utils/cryptography/MyContractDomain.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// contracts/MyContractDomain.sol | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | ||
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; | ||
|
||
/// @dev Unsafe contract to demonstrate the use of EIP712 and ECDSA. | ||
abstract contract MyContractDomain is EIP712 { | ||
function validateSignature( | ||
address mailTo, | ||
string memory mailContents, | ||
bytes memory signature | ||
) internal view returns (address) { | ||
bytes32 digest = _hashTypedDataV4( | ||
keccak256(abi.encode(keccak256("Mail(address to,string contents)"), mailTo, keccak256(bytes(mailContents)))) | ||
); | ||
return ECDSA.recover(digest, signature); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
* xref:index.adoc[Overview] | ||
* xref:utilities.adoc[Utilities] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
= Utilities | ||
|
||
Multiple libraries and general purpose utilities included in the community version of OpenZeppelin Contracts. These are only a set of utility contracts. For the full list, check out the xref:api:utils.adoc[API Reference]. | ||
|
||
== Cryptography | ||
|
||
=== Validating Typed Data Signatures | ||
|
||
_For prior knowledge on how to validate signatures on-chain, check out the https://docs.openzeppelin.com/contracts/5.x/utilities#checking_signatures_on_chain[OpenZeppelin Contracts documentation]_ | ||
|
||
As opposed to validating plain-text messages, it is possible to let your users sign structured data (i.e. typed values) in a way that is still readable on their wallets. This is possible by implementing https://docs.openzeppelin.com/contracts/api/utils#EIP712[`EIP712`], a standard way to encode structured data into a typed data hash. | ||
|
||
To start validating signed typed structures, just validate the https://docs.openzeppelin.com/contracts/api/utils#EIP712-_hashTypedDataV4-bytes32-[typed data hash]: | ||
|
||
[source,solidity] | ||
---- | ||
include::api:example$utils/cryptography/MyContractDomain.sol[] | ||
---- | ||
|
||
As part of the message, EIP-712 requires implementers to include a domain separator, which is a hash that includes the current smart contract address and the chain id where it's deployed. This way, the smart contract can be sure that the structured message was signed for its specific domain, avoiding replayability of signatures in smart contracts. | ||
|
||
==== Validating Nested EIP-712 Signatures | ||
|
||
Accounts (i.e. Smart Contract Wallets or Smart Accounts) are particularly likely to be controlled by multiple signers. As such, it's important to make sure that signatures are: | ||
|
||
1. Only valid for the intended domain and account. | ||
2. Validated in a way that's readable for the end signer. | ||
|
||
On one hand, making sure that the Account signature is only valid for an specific smart contract (i.e. an application) is difficult since it requires to validate a signature whose domain is the application but also the Account itself. For these reason, the community developed https://eips.ethereum.org/EIPS/eip-7739[ERC-7739]; a defensive rehashing mechanism that binds a signature to a single domain using a nested EIP-712 approach (i.e. an EIP-712 typed structure wrapping another). | ||
|
||
In case your smart contract validates signatures, using xref:api:utils.adoc#ERC7739Signer[`ERC7739Signer`] will implement the https://docs.openzeppelin.com/contracts/api/interfaces#IERC1271[`IERC1271`] interface for validating smart contract signatures following the approach suggested by ERC-7739: | ||
|
||
[source,solidity] | ||
---- | ||
include::api:example$utils/cryptography/ERC7739SignerECDSA.sol[] | ||
---- |