github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.19;
     3  
     4  import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
     5  import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
     6  import { Address } from "@openzeppelin/contracts/utils/Address.sol";
     7  
     8  import {
     9      AttestationRequestData,
    10      DelegatedAttestationRequest,
    11      DelegatedRevocationRequest,
    12      RevocationRequestData
    13  } from "src/EAS/IEAS.sol";
    14  
    15  import {
    16      DeadlineExpired,
    17      NO_EXPIRATION_TIME,
    18      Signature,
    19      InvalidSignature,
    20      MAX_GAP,
    21      stringToBytes32,
    22      bytes32ToString
    23  } from "src/EAS/Common.sol";
    24  
    25  /// @title EIP1271Verifier
    26  /// @notice EIP1271Verifier typed signatures verifier for EAS delegated attestations.
    27  abstract contract EIP1271Verifier is EIP712 {
    28      using Address for address;
    29  
    30      error InvalidNonce();
    31  
    32      // The hash of the data type used to relay calls to the attest function. It's the value of
    33      // keccak256("Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32
    34      // refUID,bytes data,uint256 value,uint256 nonce,uint64 deadline)").
    35      bytes32 private constant ATTEST_TYPEHASH = 0xfeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d988076;
    36  
    37      // The hash of the data type used to relay calls to the revoke function. It's the value of
    38      // keccak256("Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint256 nonce,uint64 deadline)").
    39      bytes32 private constant REVOKE_TYPEHASH = 0xb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e75;
    40  
    41      // The user readable name of the signing domain.
    42      bytes32 private immutable _name;
    43  
    44      // Replay protection nonces.
    45      mapping(address => uint256) private _nonces;
    46  
    47      // Upgrade forward-compatibility storage gap
    48      uint256[MAX_GAP - 1] private __gap;
    49  
    50      /// @dev Emitted when users invalidate nonces by increasing their nonces to (higher) new values.
    51      /// @param oldNonce The previous nonce.
    52      /// @param newNonce The new value.
    53      event NonceIncreased(uint256 oldNonce, uint256 newNonce);
    54  
    55      /// @dev Creates a new EIP1271Verifier instance.
    56      /// @param version The current major version of the signing domain
    57      constructor(string memory name, string memory version) EIP712(name, version) {
    58          _name = stringToBytes32(name);
    59      }
    60  
    61      /// @notice Returns the domain separator used in the encoding of the signatures for attest, and revoke.
    62      /// @return The domain separator used in the encoding of the signatures for attest, and revoke.
    63      function getDomainSeparator() external view returns (bytes32) {
    64          return _domainSeparatorV4();
    65      }
    66  
    67      /// @notice Returns the current nonce per-account.
    68      /// @param account The requested account.
    69      /// @return The current nonce.
    70      function getNonce(address account) external view returns (uint256) {
    71          return _nonces[account];
    72      }
    73  
    74      /// @notice Returns the EIP712 type hash for the attest function.
    75      /// @return The EIP712 type hash for the attest function.
    76      function getAttestTypeHash() external pure returns (bytes32) {
    77          return ATTEST_TYPEHASH;
    78      }
    79  
    80      /// @notice Returns the EIP712 type hash for the revoke function.
    81      /// @return The EIP712 type hash for the revoke function.
    82      function getRevokeTypeHash() external pure returns (bytes32) {
    83          return REVOKE_TYPEHASH;
    84      }
    85  
    86      /// @notice Returns the EIP712 name.
    87      /// @return The EIP712 name.
    88      function getName() external view returns (string memory) {
    89          return bytes32ToString(_name);
    90      }
    91  
    92      /// @notice Provides users an option to invalidate nonces by increasing their nonces to (higher) new values.
    93      /// @param newNonce The (higher) new value.
    94      function increaseNonce(uint256 newNonce) external {
    95          uint256 oldNonce = _nonces[msg.sender];
    96          if (newNonce <= oldNonce) {
    97              revert InvalidNonce();
    98          }
    99  
   100          _nonces[msg.sender] = newNonce;
   101  
   102          emit NonceIncreased({ oldNonce: oldNonce, newNonce: newNonce });
   103      }
   104  
   105      /// @notice Verifies delegated attestation request.
   106      /// @param request The arguments of the delegated attestation request.
   107      function _verifyAttest(DelegatedAttestationRequest memory request) internal {
   108          if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) {
   109              revert DeadlineExpired();
   110          }
   111  
   112          AttestationRequestData memory data = request.data;
   113          Signature memory signature = request.signature;
   114  
   115          bytes32 hash = _hashTypedDataV4(
   116              keccak256(
   117                  abi.encode(
   118                      ATTEST_TYPEHASH,
   119                      request.attester,
   120                      request.schema,
   121                      data.recipient,
   122                      data.expirationTime,
   123                      data.revocable,
   124                      data.refUID,
   125                      keccak256(data.data),
   126                      data.value,
   127                      _nonces[request.attester]++,
   128                      request.deadline
   129                  )
   130              )
   131          );
   132          if (
   133              !SignatureChecker.isValidSignatureNow(
   134                  request.attester, hash, abi.encodePacked(signature.r, signature.s, signature.v)
   135              )
   136          ) {
   137              revert InvalidSignature();
   138          }
   139      }
   140  
   141      /// @notice Verifies delegated revocation request.
   142      /// @param request The arguments of the delegated revocation request.
   143      function _verifyRevoke(DelegatedRevocationRequest memory request) internal {
   144          if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) {
   145              revert DeadlineExpired();
   146          }
   147  
   148          RevocationRequestData memory data = request.data;
   149          Signature memory signature = request.signature;
   150  
   151          bytes32 hash = _hashTypedDataV4(
   152              keccak256(
   153                  abi.encode(
   154                      REVOKE_TYPEHASH,
   155                      request.revoker,
   156                      request.schema,
   157                      data.uid,
   158                      data.value,
   159                      _nonces[request.revoker]++,
   160                      request.deadline
   161                  )
   162              )
   163          );
   164          if (
   165              !SignatureChecker.isValidSignatureNow(
   166                  request.revoker, hash, abi.encodePacked(signature.r, signature.s, signature.v)
   167              )
   168          ) {
   169              revert InvalidSignature();
   170          }
   171      }
   172  
   173      /// @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the
   174      ///     current block time.
   175      function _time() internal view virtual returns (uint64) {
   176          return uint64(block.timestamp);
   177      }
   178  }