-
Notifications
You must be signed in to change notification settings - Fork 7
/
EIP712Lib.sol
126 lines (116 loc) · 4.42 KB
/
EIP712Lib.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../domain/BosonConstants.sol";
import { ProtocolLib } from "../libs/ProtocolLib.sol";
/**
* @title EIP712Lib
*
* @dev Provides the domain separator and chain id.
*/
library EIP712Lib {
/**
* @notice Generates the domain separator hash.
*
* @param _name - the name of the protocol
* @param _version - The version of the protocol
* @return the domain separator hash
*/
function buildDomainSeparator(string memory _name, string memory _version) internal view returns (bytes32) {
return
keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(_name)),
keccak256(bytes(_version)),
address(this),
block.chainid
)
);
}
/**
* @notice Recovers the Signer from the Signature components.
*
* Reverts if:
* - Signer is the zero address
*
* @param _user - the sender of the transaction
* @param _hashedMetaTx - hashed meta transaction
* @param _sigR - r part of the signer's signature
* @param _sigS - s part of the signer's signature
* @param _sigV - v part of the signer's signature
* @return true if signer is same as _user parameter
*/
function verify(
address _user,
bytes32 _hashedMetaTx,
bytes32 _sigR,
bytes32 _sigS,
uint8 _sigV
) internal view returns (bool) {
// Ensure signature is unique
// See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/04695aecbd4d17dddfd55de766d10e3805d6f42f/contracts/cryptography/ECDSA.sol#63
require(
uint256(_sigS) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 &&
(_sigV == 27 || _sigV == 28),
INVALID_SIGNATURE
);
address signer = ecrecover(toTypedMessageHash(_hashedMetaTx), _sigV, _sigR, _sigS);
require(signer != address(0), INVALID_SIGNATURE);
return signer == _user;
}
/**
* @notice Gets the domain separator from storage if matches with the chain id and diamond address, else, build new domain separator.
*
* @return the domain separator
*/
function getDomainSeparator() private view returns (bytes32) {
address cachedThis = ProtocolLib.protocolMetaTxInfo().cachedThis;
uint256 cachedChainId = ProtocolLib.protocolMetaTxInfo().cachedChainId;
if (address(this) == cachedThis && block.chainid == cachedChainId) {
return ProtocolLib.protocolMetaTxInfo().domainSeparator;
} else {
return buildDomainSeparator(PROTOCOL_NAME, PROTOCOL_VERSION);
}
}
/**
* @notice Generates EIP712 compatible message hash.
*
* @dev Accepts message hash and returns hash message in EIP712 compatible form
* so that it can be used to recover signer from signature signed using EIP712 formatted data
* https://eips.ethereum.org/EIPS/eip-712
* "\\x19" makes the encoding deterministic
* "\\x01" is the version byte to make it compatible to EIP-191
*
* @param _messageHash - the message hash
* @return the EIP712 compatible message hash
*/
function toTypedMessageHash(bytes32 _messageHash) internal view returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", getDomainSeparator(), _messageHash));
}
/**
* @notice Gets the current message sender address from storage.
*
* @return the the current message sender address from storage
*/
function getCurrentSenderAddress() internal view returns (address) {
return ProtocolLib.protocolMetaTxInfo().currentSenderAddress;
}
/**
* @notice Returns the message sender address.
*
* @dev Could be msg.sender or the message sender address from storage (in case of meta transaction).
*
* @return the message sender address
*/
function msgSender() internal view returns (address) {
bool isItAMetaTransaction = ProtocolLib.protocolMetaTxInfo().isMetaTransaction;
// Get sender from the storage if this is a meta transaction
if (isItAMetaTransaction) {
address sender = getCurrentSenderAddress();
require(sender != address(0), INVALID_ADDRESS);
return sender;
} else {
return msg.sender;
}
}
}