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