-
Notifications
You must be signed in to change notification settings - Fork 122
/
IdGateway.sol
186 lines (159 loc) · 6.11 KB
/
IdGateway.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;
import {IIdGateway} from "./interfaces/IIdGateway.sol";
import {IStorageRegistry} from "./interfaces/IStorageRegistry.sol";
import {IIdRegistry} from "./interfaces/IIdRegistry.sol";
import {Guardians} from "./abstract/Guardians.sol";
import {TransferHelper} from "./libraries/TransferHelper.sol";
import {EIP712} from "./abstract/EIP712.sol";
import {Nonces} from "./abstract/Nonces.sol";
import {Signatures} from "./abstract/Signatures.sol";
/**
* @title Farcaster IdGateway
*
* @notice See https://github.com/farcasterxyz/contracts/blob/v3.1.0/docs/docs.md for an overview.
*
* @custom:security-contact [email protected]
*/
contract IdGateway is IIdGateway, Guardians, Signatures, EIP712, Nonces {
using TransferHelper for address;
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
string public constant VERSION = "2023.11.15";
/**
* @inheritdoc IIdGateway
*/
bytes32 public constant REGISTER_TYPEHASH =
keccak256("Register(address to,address recovery,uint256 nonce,uint256 deadline)");
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
IIdRegistry public immutable idRegistry;
/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
IStorageRegistry public storageRegistry;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/**
* @notice Configure IdRegistry and StorageRegistry addresses.
* Set the owner of the contract to the provided _owner.
*
* @param _idRegistry IdRegistry address.
* @param _storageRegistry StorageRegistery address.
* @param _initialOwner Initial owner address.
*
*/
constructor(
address _idRegistry,
address _storageRegistry,
address _initialOwner
) Guardians(_initialOwner) EIP712("Farcaster IdGateway", "1") {
idRegistry = IIdRegistry(_idRegistry);
storageRegistry = IStorageRegistry(_storageRegistry);
emit SetStorageRegistry(address(0), _storageRegistry);
}
/*//////////////////////////////////////////////////////////////
PRICE VIEW
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
function price() external view returns (uint256) {
return storageRegistry.unitPrice();
}
/**
* @inheritdoc IIdGateway
*/
function price(uint256 extraStorage) external view returns (uint256) {
return storageRegistry.price(1 + extraStorage);
}
/*//////////////////////////////////////////////////////////////
REGISTRATION LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
function register(address recovery) external payable returns (uint256, uint256) {
return register(recovery, 0);
}
function register(
address recovery,
uint256 extraStorage
) public payable whenNotPaused returns (uint256 fid, uint256 overpayment) {
fid = idRegistry.register(msg.sender, recovery);
overpayment = _rentStorage(fid, extraStorage, msg.value, msg.sender);
}
/**
* @inheritdoc IIdGateway
*/
function registerFor(
address to,
address recovery,
uint256 deadline,
bytes calldata sig
) external payable returns (uint256, uint256) {
return registerFor(to, recovery, deadline, sig, 0);
}
function registerFor(
address to,
address recovery,
uint256 deadline,
bytes calldata sig,
uint256 extraStorage
) public payable whenNotPaused returns (uint256 fid, uint256 overpayment) {
/* Revert if signature is invalid */
_verifyRegisterSig({to: to, recovery: recovery, deadline: deadline, sig: sig});
fid = idRegistry.register(to, recovery);
overpayment = _rentStorage(fid, extraStorage, msg.value, msg.sender);
}
/*//////////////////////////////////////////////////////////////
PERMISSIONED ACTIONS
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IIdGateway
*/
function setStorageRegistry(address _storageRegistry) external onlyOwner {
emit SetStorageRegistry(address(storageRegistry), _storageRegistry);
storageRegistry = IStorageRegistry(_storageRegistry);
}
/*//////////////////////////////////////////////////////////////
SIGNATURE VERIFICATION HELPERS
//////////////////////////////////////////////////////////////*/
function _verifyRegisterSig(address to, address recovery, uint256 deadline, bytes memory sig) internal {
_verifySig(
_hashTypedDataV4(keccak256(abi.encode(REGISTER_TYPEHASH, to, recovery, _useNonce(to), deadline))),
to,
deadline,
sig
);
}
/*//////////////////////////////////////////////////////////////
STORAGE RENTAL HELPERS
//////////////////////////////////////////////////////////////*/
function _rentStorage(
uint256 fid,
uint256 extraUnits,
uint256 payment,
address payer
) internal returns (uint256 overpayment) {
overpayment = storageRegistry.rent{value: payment}(fid, 1 + extraUnits);
if (overpayment > 0) {
payer.sendNative(overpayment);
}
}
receive() external payable {
if (msg.sender != address(storageRegistry)) revert Unauthorized();
}
}