@evvm/testnet-contracts 2.2.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +145 -118
- package/README.md +162 -39
- package/contracts/core/Core.sol +1394 -0
- package/contracts/core/lib/CoreStorage.sol +171 -0
- package/contracts/nameService/NameService.sol +666 -586
- package/contracts/nameService/lib/IdentityValidation.sol +18 -3
- package/contracts/p2pSwap/P2PSwap.sol +439 -285
- package/contracts/staking/Estimator.sol +128 -40
- package/contracts/staking/Staking.sol +329 -322
- package/contracts/treasury/Treasury.sol +48 -37
- package/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +585 -198
- package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +425 -174
- package/contracts/treasuryTwoChains/lib/PayloadUtils.sol +2 -4
- package/interfaces/{IEvvm.sol → ICore.sol} +67 -29
- package/interfaces/IEstimator.sol +1 -1
- package/interfaces/INameService.sol +58 -52
- package/interfaces/IP2PSwap.sol +18 -17
- package/interfaces/IStaking.sol +22 -17
- package/interfaces/ITreasury.sol +2 -1
- package/interfaces/ITreasuryExternalChainStation.sol +15 -9
- package/interfaces/ITreasuryHostChainStation.sol +14 -11
- package/interfaces/IUserValidator.sol +6 -0
- package/library/Erc191TestBuilder.sol +350 -297
- package/library/EvvmService.sol +38 -27
- package/library/errors/CoreError.sol +116 -0
- package/library/errors/CrossChainTreasuryError.sol +36 -0
- package/library/errors/NameServiceError.sol +79 -0
- package/library/errors/StakingError.sol +79 -0
- package/library/errors/TreasuryError.sol +33 -0
- package/library/primitives/SignatureRecover.sol +33 -0
- package/library/structs/CoreStructs.sol +146 -0
- package/library/structs/ExternalChainStationStructs.sol +92 -0
- package/library/structs/HostChainStationStructs.sol +77 -0
- package/library/structs/NameServiceStructs.sol +47 -0
- package/library/structs/P2PSwapStructs.sol +127 -0
- package/library/structs/StakingStructs.sol +67 -0
- package/library/utils/AdvancedStrings.sol +84 -5
- package/library/utils/CAUtils.sol +29 -0
- package/library/utils/SignatureUtil.sol +34 -0
- package/library/utils/governance/Admin.sol +66 -0
- package/library/utils/governance/ProposalStructs.sol +49 -0
- package/library/utils/service/CoreExecution.sol +177 -0
- package/library/utils/service/StakingServiceUtils.sol +30 -3
- package/library/utils/signature/CoreHashUtils.sol +73 -0
- package/library/utils/signature/NameServiceHashUtils.sol +156 -0
- package/library/utils/signature/P2PSwapHashUtils.sol +65 -0
- package/library/utils/signature/StakingHashUtils.sol +41 -0
- package/library/utils/signature/TreasuryCrossChainHashUtils.sol +40 -0
- package/package.json +2 -1
- package/contracts/evvm/Evvm.sol +0 -1327
- package/contracts/evvm/lib/ErrorsLib.sol +0 -18
- package/contracts/evvm/lib/EvvmStorage.sol +0 -62
- package/contracts/evvm/lib/EvvmStructs.sol +0 -90
- package/contracts/evvm/lib/SignatureUtils.sol +0 -120
- package/contracts/nameService/lib/ErrorsLib.sol +0 -21
- package/contracts/nameService/lib/NameServiceStructs.sol +0 -69
- package/contracts/nameService/lib/SignatureUtils.sol +0 -245
- package/contracts/p2pSwap/lib/P2PSwapStructs.sol +0 -59
- package/contracts/p2pSwap/lib/SignatureUtils.sol +0 -98
- package/contracts/staking/lib/ErrorsLib.sol +0 -22
- package/contracts/staking/lib/SignatureUtils.sol +0 -39
- package/contracts/staking/lib/StakingStructs.sol +0 -94
- package/contracts/treasury/lib/ErrorsLib.sol +0 -11
- package/contracts/treasuryTwoChains/lib/ErrorsLib.sol +0 -48
- package/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +0 -80
- package/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +0 -87
- package/contracts/treasuryTwoChains/lib/SignatureUtils.sol +0 -79
- package/library/utils/GovernanceUtils.sol +0 -81
- package/library/utils/nonces/AsyncNonce.sol +0 -32
- package/library/utils/nonces/SyncNonce.sol +0 -27
- package/library/utils/service/EvvmPayments.sol +0 -79
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
// Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
NameServiceError as Error
|
|
8
|
+
} from "@evvm/testnet-contracts/library/errors/NameServiceError.sol";
|
|
9
|
+
import {
|
|
10
|
+
NameServiceHashUtils as Hash
|
|
11
|
+
} from "@evvm/testnet-contracts/library/utils/signature/NameServiceHashUtils.sol";
|
|
12
|
+
import {
|
|
13
|
+
NameServiceStructs as Structs
|
|
14
|
+
} from "@evvm/testnet-contracts/library/structs/NameServiceStructs.sol";
|
|
15
|
+
import {
|
|
16
|
+
IdentityValidation
|
|
17
|
+
} from "@evvm/testnet-contracts/contracts/nameService/lib/IdentityValidation.sol";
|
|
18
|
+
|
|
19
|
+
import {Core} from "@evvm/testnet-contracts/contracts/core/Core.sol";
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
AdvancedStrings
|
|
23
|
+
} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
|
|
24
|
+
import {
|
|
25
|
+
ProposalStructs
|
|
26
|
+
} from "@evvm/testnet-contracts/library/utils/governance/ProposalStructs.sol";
|
|
27
|
+
|
|
5
28
|
/**
|
|
6
29
|
_ _
|
|
7
30
|
| \ | |
|
|
@@ -25,346 +48,264 @@ pragma solidity ^0.8.0;
|
|
|
25
48
|
██║ ██╔══╝ ╚════██║ ██║ ██║╚██╗██║██╔══╝ ██║
|
|
26
49
|
██║ ███████╗███████║ ██║ ██║ ╚████║███████╗ ██║
|
|
27
50
|
╚═╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
|
|
28
|
-
*
|
|
29
|
-
* @title EVVM Name Service Contract
|
|
51
|
+
* @title EVVM Name Service
|
|
30
52
|
* @author Mate labs
|
|
31
|
-
* @notice
|
|
32
|
-
* @dev
|
|
33
|
-
*
|
|
34
|
-
* Core
|
|
35
|
-
* - Username registration with pre-registration protection against front-running
|
|
36
|
-
* - Custom metadata management with schema-based data storage
|
|
37
|
-
* - Username trading system with offers and marketplace functionality
|
|
38
|
-
* - Renewal system with dynamic pricing based on market demand
|
|
39
|
-
* - Time-delayed governance for administrative functions
|
|
40
|
-
*
|
|
41
|
-
* Registration Process:
|
|
42
|
-
* 1. Pre-register: Commit to a username hash to prevent front-running
|
|
43
|
-
* 2. Register: Reveal the username and complete registration within 30 minutes
|
|
44
|
-
* 3. Manage: Add custom metadata, handle offers, and renew as needed
|
|
45
|
-
*
|
|
46
|
-
* Security Features:
|
|
47
|
-
* - Signature verification for all operations
|
|
48
|
-
* - Nonce-based replay protection
|
|
49
|
-
* - Time-locked administrative changes
|
|
50
|
-
* - Integration with EVVM core for secure payments
|
|
51
|
-
*
|
|
52
|
-
* Economic Model:
|
|
53
|
-
* - Registration costs 100x EVVM reward amount
|
|
54
|
-
* - Custom metadata operations cost 10x EVVM reward amount
|
|
55
|
-
* - Renewal pricing varies based on market demand and timing
|
|
56
|
-
* - Marketplace takes 0.5% fee on username sales
|
|
53
|
+
* @notice Identity and username registration system for the EVVM ecosystem.
|
|
54
|
+
* @dev Manages username registration via a commit-reveal scheme (pre-registration),
|
|
55
|
+
* a secondary marketplace for domain trading, and customizable user metadata.
|
|
56
|
+
* Integrates with Core.sol for payment processing and uses async nonces for high throughput.
|
|
57
57
|
*/
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
AsyncNonce
|
|
62
|
-
} from "@evvm/testnet-contracts/library/utils/nonces/AsyncNonce.sol";
|
|
63
|
-
import {
|
|
64
|
-
NameServiceStructs
|
|
65
|
-
} from "@evvm/testnet-contracts/contracts/nameService/lib/NameServiceStructs.sol";
|
|
66
|
-
import {
|
|
67
|
-
AdvancedStrings
|
|
68
|
-
} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
|
|
69
|
-
import {
|
|
70
|
-
ErrorsLib
|
|
71
|
-
} from "@evvm/testnet-contracts/contracts/nameService/lib/ErrorsLib.sol";
|
|
72
|
-
import {
|
|
73
|
-
SignatureUtils
|
|
74
|
-
} from "@evvm/testnet-contracts/contracts/nameService/lib/SignatureUtils.sol";
|
|
75
|
-
import {
|
|
76
|
-
IdentityValidation
|
|
77
|
-
} from "@evvm/testnet-contracts/contracts/nameService/lib/IdentityValidation.sol";
|
|
78
|
-
|
|
79
|
-
contract NameService is AsyncNonce, NameServiceStructs {
|
|
80
|
-
/// @dev Time delay constant for accepting proposals
|
|
59
|
+
contract NameService {
|
|
60
|
+
/// @dev Time delay for accepting proposals (1 day)
|
|
81
61
|
uint256 constant TIME_TO_ACCEPT_PROPOSAL = 1 days;
|
|
82
62
|
|
|
83
|
-
/// @dev
|
|
84
|
-
address private constant PRINCIPAL_TOKEN_ADDRESS =
|
|
85
|
-
0x0000000000000000000000000000000000000001;
|
|
86
|
-
|
|
87
|
-
/// @dev Amount of Principal Tokens locked in pending marketplace offers
|
|
63
|
+
/// @dev Principal Tokens locked in pending marketplace
|
|
88
64
|
uint256 private principalTokenTokenLockedForWithdrawOffers;
|
|
89
65
|
|
|
90
|
-
/// @dev Nested mapping: username => offer ID => offer
|
|
91
|
-
mapping(string username => mapping(uint256 id => OfferMetadata))
|
|
66
|
+
/// @dev Nested mapping: username => offer ID => offer
|
|
67
|
+
mapping(string username => mapping(uint256 id => Structs.OfferMetadata))
|
|
92
68
|
private usernameOffers;
|
|
93
69
|
|
|
94
|
-
/// @dev Nested mapping: username =>
|
|
70
|
+
/// @dev Nested mapping: username => key => custom value
|
|
95
71
|
mapping(string username => mapping(uint256 numberKey => string customValue))
|
|
96
72
|
private identityCustomMetadata;
|
|
97
73
|
|
|
98
|
-
/// @dev Proposal system for token withdrawal
|
|
99
|
-
UintTypeProposal amountToWithdrawTokens;
|
|
74
|
+
/// @dev Proposal system for token withdrawal with delay
|
|
75
|
+
ProposalStructs.UintTypeProposal amountToWithdrawTokens;
|
|
100
76
|
|
|
101
|
-
/// @dev Proposal system for
|
|
102
|
-
AddressTypeProposal
|
|
77
|
+
/// @dev Proposal system for Core address changes
|
|
78
|
+
ProposalStructs.AddressTypeProposal coreAddress;
|
|
103
79
|
|
|
104
|
-
/// @dev Proposal system for admin address changes
|
|
105
|
-
AddressTypeProposal admin;
|
|
80
|
+
/// @dev Proposal system for admin address changes
|
|
81
|
+
ProposalStructs.AddressTypeProposal admin;
|
|
106
82
|
|
|
107
|
-
/// @dev Mapping from username to
|
|
108
|
-
mapping(string username => IdentityBaseMetadata basicMetadata)
|
|
83
|
+
/// @dev Mapping from username to core metadata
|
|
84
|
+
mapping(string username => Structs.IdentityBaseMetadata basicMetadata)
|
|
109
85
|
private identityDetails;
|
|
110
86
|
|
|
111
|
-
|
|
87
|
+
/// @dev EVVM contract for payment processing
|
|
88
|
+
Core private core;
|
|
112
89
|
|
|
113
|
-
/// @dev Restricts function access to
|
|
90
|
+
/// @dev Restricts function access to current admin only
|
|
114
91
|
modifier onlyAdmin() {
|
|
115
|
-
if (msg.sender != admin.current) revert
|
|
92
|
+
if (msg.sender != admin.current) revert Error.SenderIsNotAdmin();
|
|
116
93
|
|
|
117
94
|
_;
|
|
118
95
|
}
|
|
119
96
|
|
|
120
|
-
|
|
121
|
-
modifier onlyOwnerOfIdentity(address _user, string memory _identity) {
|
|
122
|
-
if (identityDetails[_identity].owner != _user)
|
|
123
|
-
revert ErrorsLib.UserIsNotOwnerOfIdentity();
|
|
124
|
-
|
|
125
|
-
_;
|
|
126
|
-
}
|
|
97
|
+
//█ Initialization ████████████████████████████████████████████████████████████████████████
|
|
127
98
|
|
|
128
99
|
/**
|
|
129
|
-
* @notice Initializes the NameService contract
|
|
130
|
-
* @
|
|
131
|
-
* @param
|
|
132
|
-
* @param _initialOwner Address that will have admin privileges
|
|
100
|
+
* @notice Initializes the NameService with the Core contract and initial administrator.
|
|
101
|
+
* @param _coreAddress The address of the EVVM Core contract.
|
|
102
|
+
* @param _initialOwner The address granted administrative privileges.
|
|
133
103
|
*/
|
|
134
|
-
constructor(address
|
|
135
|
-
|
|
104
|
+
constructor(address _coreAddress, address _initialOwner) {
|
|
105
|
+
coreAddress.current = _coreAddress;
|
|
136
106
|
admin.current = _initialOwner;
|
|
137
|
-
|
|
107
|
+
core = Core(_coreAddress);
|
|
138
108
|
}
|
|
139
109
|
|
|
110
|
+
//█ Registration Functions ████████████████████████████████████████████████████████████████████████
|
|
111
|
+
|
|
140
112
|
/**
|
|
141
|
-
* @notice
|
|
142
|
-
* @dev
|
|
143
|
-
* @param user
|
|
144
|
-
* @param hashPreRegisteredUsername
|
|
145
|
-
* @param
|
|
146
|
-
* @param
|
|
147
|
-
* @param
|
|
148
|
-
* @param
|
|
149
|
-
* @param
|
|
150
|
-
* @param
|
|
113
|
+
* @notice Commits a username hash to prevent front-running before registration.
|
|
114
|
+
* @dev Part of the commit-reveal scheme. Valid for 30 minutes.
|
|
115
|
+
* @param user The address of the registrant.
|
|
116
|
+
* @param hashPreRegisteredUsername The keccak256 hash of (username + secret).
|
|
117
|
+
* @param originExecutor Optional tx.origin restriction.
|
|
118
|
+
* @param nonce Async nonce for signature verification.
|
|
119
|
+
* @param signature Registrant's authorization signature.
|
|
120
|
+
* @param priorityFeePay Optional priority fee for the executor.
|
|
121
|
+
* @param noncePay Nonce for the Core payment (if fee is paid).
|
|
122
|
+
* @param signaturePay Signature for the Core payment (if fee is paid).
|
|
151
123
|
*/
|
|
152
124
|
function preRegistrationUsername(
|
|
153
125
|
address user,
|
|
154
126
|
bytes32 hashPreRegisteredUsername,
|
|
127
|
+
address originExecutor,
|
|
155
128
|
uint256 nonce,
|
|
156
129
|
bytes memory signature,
|
|
157
|
-
uint256
|
|
158
|
-
uint256
|
|
159
|
-
|
|
160
|
-
bytes memory signature_EVVM
|
|
130
|
+
uint256 priorityFeePay,
|
|
131
|
+
uint256 noncePay,
|
|
132
|
+
bytes memory signaturePay
|
|
161
133
|
) external {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
)
|
|
170
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
171
|
-
|
|
172
|
-
verifyAsyncNonce(user, nonce);
|
|
173
|
-
|
|
174
|
-
if (priorityFee_EVVM > 0) {
|
|
175
|
-
makePay(
|
|
176
|
-
user,
|
|
177
|
-
0,
|
|
178
|
-
priorityFee_EVVM,
|
|
179
|
-
nonce_EVVM,
|
|
180
|
-
priorityFlag_EVVM,
|
|
181
|
-
signature_EVVM
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
string memory key = string.concat(
|
|
186
|
-
"@",
|
|
187
|
-
AdvancedStrings.bytes32ToString(hashPreRegisteredUsername)
|
|
134
|
+
core.validateAndConsumeNonce(
|
|
135
|
+
user,
|
|
136
|
+
Hash.hashDataForPreRegistrationUsername(hashPreRegisteredUsername),
|
|
137
|
+
originExecutor,
|
|
138
|
+
nonce,
|
|
139
|
+
true,
|
|
140
|
+
signature
|
|
188
141
|
);
|
|
189
142
|
|
|
190
|
-
|
|
143
|
+
if (priorityFeePay > 0)
|
|
144
|
+
requestPay(user, 0, priorityFeePay, noncePay, signaturePay);
|
|
145
|
+
|
|
146
|
+
identityDetails[
|
|
147
|
+
string.concat(
|
|
148
|
+
"@",
|
|
149
|
+
AdvancedStrings.bytes32ToString(hashPreRegisteredUsername)
|
|
150
|
+
)
|
|
151
|
+
] = Structs.IdentityBaseMetadata({
|
|
191
152
|
owner: user,
|
|
192
|
-
|
|
153
|
+
expirationDate: block.timestamp + 30 minutes,
|
|
193
154
|
customMetadataMaxSlots: 0,
|
|
194
155
|
offerMaxSlots: 0,
|
|
195
156
|
flagNotAUsername: 0x01
|
|
196
157
|
});
|
|
197
158
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
|
|
201
|
-
makeCaPay(
|
|
202
|
-
msg.sender,
|
|
203
|
-
IEvvm(evvmAddress.current).getRewardAmount() + priorityFee_EVVM
|
|
204
|
-
);
|
|
205
|
-
}
|
|
159
|
+
if (core.isAddressStaker(msg.sender))
|
|
160
|
+
makeCaPay(msg.sender, core.getRewardAmount() + priorityFeePay);
|
|
206
161
|
}
|
|
207
162
|
|
|
208
163
|
/**
|
|
209
|
-
* @notice
|
|
210
|
-
* @dev
|
|
211
|
-
* @param user
|
|
212
|
-
* @param username The
|
|
213
|
-
* @param
|
|
214
|
-
* @param
|
|
215
|
-
* @param
|
|
216
|
-
* @param
|
|
217
|
-
* @param
|
|
218
|
-
* @param
|
|
219
|
-
* @param
|
|
164
|
+
* @notice Finalizes username registration by revealing the secret associated with a pre-registration.
|
|
165
|
+
* @dev Validates format, availability, and payment. Grants 1 year of ownership.
|
|
166
|
+
* @param user The address of the registrant.
|
|
167
|
+
* @param username The plain-text username being registered.
|
|
168
|
+
* @param lockNumber The secret used in the pre-registration hash.
|
|
169
|
+
* @param originExecutor Optional tx.origin restriction.
|
|
170
|
+
* @param nonce Async nonce for signature verification.
|
|
171
|
+
* @param signature Registrant's authorization signature.
|
|
172
|
+
* @param priorityFeePay Optional priority fee for the executor.
|
|
173
|
+
* @param noncePay Nonce for the Core payment (registration fee + priority fee).
|
|
174
|
+
* @param signaturePay Signature for the Core payment.
|
|
220
175
|
*/
|
|
221
176
|
function registrationUsername(
|
|
222
177
|
address user,
|
|
223
178
|
string memory username,
|
|
224
|
-
uint256
|
|
179
|
+
uint256 lockNumber,
|
|
180
|
+
address originExecutor,
|
|
225
181
|
uint256 nonce,
|
|
226
182
|
bytes memory signature,
|
|
227
|
-
uint256
|
|
228
|
-
uint256
|
|
229
|
-
|
|
230
|
-
bytes memory signature_EVVM
|
|
183
|
+
uint256 priorityFeePay,
|
|
184
|
+
uint256 noncePay,
|
|
185
|
+
bytes memory signaturePay
|
|
231
186
|
) external {
|
|
187
|
+
core.validateAndConsumeNonce(
|
|
188
|
+
user,
|
|
189
|
+
Hash.hashDataForRegistrationUsername(username, lockNumber),
|
|
190
|
+
originExecutor,
|
|
191
|
+
nonce,
|
|
192
|
+
true,
|
|
193
|
+
signature
|
|
194
|
+
);
|
|
195
|
+
|
|
232
196
|
if (
|
|
233
197
|
admin.current != user &&
|
|
234
198
|
!IdentityValidation.isValidUsername(username)
|
|
235
|
-
) revert
|
|
199
|
+
) revert Error.InvalidUsername();
|
|
236
200
|
|
|
237
201
|
if (!isUsernameAvailable(username))
|
|
238
|
-
revert
|
|
239
|
-
|
|
240
|
-
if (
|
|
241
|
-
!SignatureUtils.verifyMessageSignedForRegistrationUsername(
|
|
242
|
-
IEvvm(evvmAddress.current).getEvvmID(),
|
|
243
|
-
user,
|
|
244
|
-
username,
|
|
245
|
-
clowNumber,
|
|
246
|
-
nonce,
|
|
247
|
-
signature
|
|
248
|
-
)
|
|
249
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
250
|
-
|
|
251
|
-
verifyAsyncNonce(user, nonce);
|
|
202
|
+
revert Error.UsernameAlreadyRegistered();
|
|
252
203
|
|
|
253
|
-
|
|
204
|
+
requestPay(
|
|
254
205
|
user,
|
|
255
206
|
getPriceOfRegistration(username),
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
signature_EVVM
|
|
207
|
+
priorityFeePay,
|
|
208
|
+
noncePay,
|
|
209
|
+
signaturePay
|
|
260
210
|
);
|
|
261
211
|
|
|
262
212
|
string memory _key = string.concat(
|
|
263
213
|
"@",
|
|
264
|
-
AdvancedStrings.bytes32ToString(hashUsername(username,
|
|
214
|
+
AdvancedStrings.bytes32ToString(hashUsername(username, lockNumber))
|
|
265
215
|
);
|
|
266
216
|
|
|
267
217
|
if (
|
|
268
218
|
identityDetails[_key].owner != user ||
|
|
269
|
-
identityDetails[_key].
|
|
270
|
-
) revert
|
|
219
|
+
identityDetails[_key].expirationDate > block.timestamp
|
|
220
|
+
) revert Error.PreRegistrationNotValid();
|
|
271
221
|
|
|
272
|
-
identityDetails[username] = IdentityBaseMetadata({
|
|
222
|
+
identityDetails[username] = Structs.IdentityBaseMetadata({
|
|
273
223
|
owner: user,
|
|
274
|
-
|
|
224
|
+
expirationDate: block.timestamp + 366 days,
|
|
275
225
|
customMetadataMaxSlots: 0,
|
|
276
226
|
offerMaxSlots: 0,
|
|
277
227
|
flagNotAUsername: 0x00
|
|
278
228
|
});
|
|
279
229
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
|
|
230
|
+
if (core.isAddressStaker(msg.sender))
|
|
283
231
|
makeCaPay(
|
|
284
232
|
msg.sender,
|
|
285
|
-
(50 *
|
|
286
|
-
priorityFee_EVVM
|
|
233
|
+
(50 * core.getRewardAmount()) + priorityFeePay
|
|
287
234
|
);
|
|
288
|
-
}
|
|
289
235
|
|
|
290
236
|
delete identityDetails[_key];
|
|
291
237
|
}
|
|
292
238
|
|
|
239
|
+
//█ Marketplace Functions ████████████████████████████████████████████████████████████████████████
|
|
240
|
+
|
|
293
241
|
/**
|
|
294
|
-
* @notice
|
|
295
|
-
* @dev
|
|
296
|
-
* @param user
|
|
297
|
-
* @param username
|
|
298
|
-
* @param
|
|
299
|
-
* @param
|
|
300
|
-
* @param
|
|
301
|
-
* @param
|
|
302
|
-
* @param
|
|
303
|
-
* @param
|
|
304
|
-
* @param
|
|
305
|
-
* @param
|
|
306
|
-
* @return offerID
|
|
242
|
+
* @notice Places a purchase offer on an existing username.
|
|
243
|
+
* @dev Tokens are locked in the contract. A 0.5% marketplace fee is applied upon successful sale.
|
|
244
|
+
* @param user The address of the offerer.
|
|
245
|
+
* @param username The target username.
|
|
246
|
+
* @param amount Total amount offered (including fee).
|
|
247
|
+
* @param expirationDate When the offer expires.
|
|
248
|
+
* @param originExecutor Optional tx.origin restriction.
|
|
249
|
+
* @param nonce Async nonce for signature verification.
|
|
250
|
+
* @param signature Offerer's authorization signature.
|
|
251
|
+
* @param priorityFeePay Optional priority fee for the executor.
|
|
252
|
+
* @param noncePay Nonce for the Core payment (locks tokens).
|
|
253
|
+
* @param signaturePay Signature for the Core payment.
|
|
254
|
+
* @return offerID The unique ID of the created offer.
|
|
307
255
|
*/
|
|
308
256
|
function makeOffer(
|
|
309
257
|
address user,
|
|
310
258
|
string memory username,
|
|
311
|
-
uint256 expireDate,
|
|
312
259
|
uint256 amount,
|
|
260
|
+
uint256 expirationDate,
|
|
261
|
+
address originExecutor,
|
|
313
262
|
uint256 nonce,
|
|
314
263
|
bytes memory signature,
|
|
315
|
-
uint256
|
|
316
|
-
uint256
|
|
317
|
-
|
|
318
|
-
bytes memory signature_EVVM
|
|
264
|
+
uint256 priorityFeePay,
|
|
265
|
+
uint256 noncePay,
|
|
266
|
+
bytes memory signaturePay
|
|
319
267
|
) external returns (uint256 offerID) {
|
|
268
|
+
core.validateAndConsumeNonce(
|
|
269
|
+
user,
|
|
270
|
+
Hash.hashDataForMakeOffer(username, amount, expirationDate),
|
|
271
|
+
originExecutor,
|
|
272
|
+
nonce,
|
|
273
|
+
true,
|
|
274
|
+
signature
|
|
275
|
+
);
|
|
276
|
+
|
|
320
277
|
if (
|
|
321
278
|
identityDetails[username].flagNotAUsername == 0x01 ||
|
|
322
|
-
!verifyIfIdentityExists(username)
|
|
323
|
-
|
|
324
|
-
expireDate <= block.timestamp
|
|
325
|
-
) revert ErrorsLib.PreRegistrationNotValid();
|
|
279
|
+
!verifyIfIdentityExists(username)
|
|
280
|
+
) revert Error.InvalidUsername();
|
|
326
281
|
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
IEvvm(evvmAddress.current).getEvvmID(),
|
|
330
|
-
user,
|
|
331
|
-
username,
|
|
332
|
-
expireDate,
|
|
333
|
-
amount,
|
|
334
|
-
nonce,
|
|
335
|
-
signature
|
|
336
|
-
)
|
|
337
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
282
|
+
if (expirationDate <= block.timestamp)
|
|
283
|
+
revert Error.CannotBeBeforeCurrentTime();
|
|
338
284
|
|
|
339
|
-
|
|
285
|
+
if (amount == 0) revert Error.AmountMustBeGreaterThanZero();
|
|
340
286
|
|
|
341
|
-
|
|
342
|
-
user,
|
|
343
|
-
amount,
|
|
344
|
-
priorityFee_EVVM,
|
|
345
|
-
nonce_EVVM,
|
|
346
|
-
priorityFlag_EVVM,
|
|
347
|
-
signature_EVVM
|
|
348
|
-
);
|
|
287
|
+
requestPay(user, amount, priorityFeePay, noncePay, signaturePay);
|
|
349
288
|
|
|
350
|
-
while (usernameOffers[username][offerID].offerer != address(0))
|
|
289
|
+
while (usernameOffers[username][offerID].offerer != address(0))
|
|
351
290
|
offerID++;
|
|
352
|
-
}
|
|
353
291
|
|
|
354
|
-
|
|
292
|
+
uint256 amountToOffer = ((amount * 995) / 1000);
|
|
293
|
+
|
|
294
|
+
usernameOffers[username][offerID] = Structs.OfferMetadata({
|
|
355
295
|
offerer: user,
|
|
356
|
-
|
|
357
|
-
amount:
|
|
296
|
+
expirationDate: expirationDate,
|
|
297
|
+
amount: amountToOffer
|
|
358
298
|
});
|
|
359
299
|
|
|
360
300
|
makeCaPay(
|
|
361
301
|
msg.sender,
|
|
362
|
-
|
|
302
|
+
core.getRewardAmount() +
|
|
363
303
|
((amount * 125) / 100_000) +
|
|
364
|
-
|
|
304
|
+
priorityFeePay
|
|
365
305
|
);
|
|
306
|
+
|
|
366
307
|
principalTokenTokenLockedForWithdrawOffers +=
|
|
367
|
-
|
|
308
|
+
amountToOffer +
|
|
368
309
|
(amount / 800);
|
|
369
310
|
|
|
370
311
|
if (offerID > identityDetails[username].offerMaxSlots) {
|
|
@@ -372,60 +313,70 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
372
313
|
} else if (identityDetails[username].offerMaxSlots == 0) {
|
|
373
314
|
identityDetails[username].offerMaxSlots++;
|
|
374
315
|
}
|
|
375
|
-
|
|
376
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
377
316
|
}
|
|
378
317
|
|
|
379
318
|
/**
|
|
380
|
-
* @notice Withdraws
|
|
381
|
-
* @dev Can only be called by
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
319
|
+
* @notice Withdraws marketplace offer and refunds tokens
|
|
320
|
+
* @dev Can only be called by offer creator or after expire
|
|
321
|
+
*
|
|
322
|
+
* Withdrawal Flow:
|
|
323
|
+
* 1. Validates offer exists and belongs to user
|
|
324
|
+
* 2. Optionally validates expiration date passed
|
|
325
|
+
* 3. Refunds locked tokens to offerer
|
|
326
|
+
* 4. Processes optional priority fee
|
|
327
|
+
* 5. Deletes offer and updates slot count
|
|
328
|
+
*
|
|
329
|
+
* Core.sol Integration:
|
|
330
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
331
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
332
|
+
* - Hash includes username + offer ID
|
|
333
|
+
* - Prevents replay attacks and double withdrawals
|
|
334
|
+
*
|
|
335
|
+
* Core.sol Integration:
|
|
336
|
+
* - Refund: offer amount via makeTransfer to offerer
|
|
337
|
+
* - Priority fee: via requestPay (if > 0)
|
|
338
|
+
* - Staker reward: 1x reward + priority fee
|
|
339
|
+
* - makeCaPay distributes to caller if staker
|
|
340
|
+
*
|
|
341
|
+
* Token Unlocking:
|
|
342
|
+
* - Decreases principalTokenTokenLockedForWithdrawOffers
|
|
343
|
+
* - Releases both offer amount and marketplace fee
|
|
344
|
+
* - Returns funds to original offerer
|
|
345
|
+
*
|
|
346
|
+
* @param user Address that made original offer
|
|
347
|
+
* @param username Username offer was made for
|
|
348
|
+
* @param offerID Unique identifier of offer to withdraw
|
|
349
|
+
* @param nonce Async nonce for replay protection
|
|
350
|
+
* @param signature Signature for Core.sol validation
|
|
351
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
352
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
353
|
+
* @param signaturePay Signature for EVVM payment
|
|
391
354
|
*/
|
|
392
355
|
function withdrawOffer(
|
|
393
356
|
address user,
|
|
394
357
|
string memory username,
|
|
395
358
|
uint256 offerID,
|
|
359
|
+
address originExecutor,
|
|
396
360
|
uint256 nonce,
|
|
397
361
|
bytes memory signature,
|
|
398
|
-
uint256
|
|
399
|
-
uint256
|
|
400
|
-
|
|
401
|
-
bytes memory signature_EVVM
|
|
362
|
+
uint256 priorityFeePay,
|
|
363
|
+
uint256 noncePay,
|
|
364
|
+
bytes memory signaturePay
|
|
402
365
|
) external {
|
|
366
|
+
core.validateAndConsumeNonce(
|
|
367
|
+
user,
|
|
368
|
+
Hash.hashDataForWithdrawOffer(username, offerID),
|
|
369
|
+
originExecutor,
|
|
370
|
+
nonce,
|
|
371
|
+
true,
|
|
372
|
+
signature
|
|
373
|
+
);
|
|
374
|
+
|
|
403
375
|
if (usernameOffers[username][offerID].offerer != user)
|
|
404
|
-
revert
|
|
376
|
+
revert Error.UserIsNotOwnerOfOffer();
|
|
405
377
|
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
IEvvm(evvmAddress.current).getEvvmID(),
|
|
409
|
-
user,
|
|
410
|
-
username,
|
|
411
|
-
offerID,
|
|
412
|
-
nonce,
|
|
413
|
-
signature
|
|
414
|
-
)
|
|
415
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
416
|
-
|
|
417
|
-
verifyAsyncNonce(user, nonce);
|
|
418
|
-
|
|
419
|
-
if (priorityFee_EVVM > 0) {
|
|
420
|
-
makePay(
|
|
421
|
-
user,
|
|
422
|
-
0,
|
|
423
|
-
priorityFee_EVVM,
|
|
424
|
-
nonce_EVVM,
|
|
425
|
-
priorityFlag_EVVM,
|
|
426
|
-
signature_EVVM
|
|
427
|
-
);
|
|
428
|
-
}
|
|
378
|
+
if (priorityFeePay > 0)
|
|
379
|
+
requestPay(user, 0, priorityFeePay, noncePay, signaturePay);
|
|
429
380
|
|
|
430
381
|
makeCaPay(user, usernameOffers[username][offerID].amount);
|
|
431
382
|
|
|
@@ -433,69 +384,91 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
433
384
|
|
|
434
385
|
makeCaPay(
|
|
435
386
|
msg.sender,
|
|
436
|
-
|
|
387
|
+
core.getRewardAmount() +
|
|
437
388
|
((usernameOffers[username][offerID].amount * 1) / 796) +
|
|
438
|
-
|
|
389
|
+
priorityFeePay
|
|
439
390
|
);
|
|
440
391
|
|
|
441
392
|
principalTokenTokenLockedForWithdrawOffers -=
|
|
442
393
|
(usernameOffers[username][offerID].amount) +
|
|
443
394
|
(((usernameOffers[username][offerID].amount * 1) / 199) / 4);
|
|
444
|
-
|
|
445
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
446
395
|
}
|
|
447
396
|
|
|
448
397
|
/**
|
|
449
|
-
* @notice Accepts
|
|
450
|
-
* @dev Can only be called by
|
|
451
|
-
*
|
|
398
|
+
* @notice Accepts marketplace offer and transfers ownership
|
|
399
|
+
* @dev Can only be called by current owner before expiration
|
|
400
|
+
*
|
|
401
|
+
* Acceptance Flow:
|
|
402
|
+
* 1. Validates user is current username owner
|
|
403
|
+
* 2. Validates offer exists and not expired
|
|
404
|
+
* 3. Transfers offer amount to seller
|
|
405
|
+
* 4. Transfers ownership to offerer
|
|
406
|
+
* 5. Processes optional priority fee
|
|
407
|
+
* 6. Deletes offer and unlocks tokens
|
|
408
|
+
*
|
|
409
|
+
* Core.sol Integration:
|
|
410
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
411
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
412
|
+
* - Hash includes username + offer ID
|
|
413
|
+
* - Prevents replay attacks and double acceptance
|
|
414
|
+
*
|
|
415
|
+
* Core.sol Integration:
|
|
416
|
+
* - Payment: offer amount via makeCaPay to seller
|
|
417
|
+
* - Priority fee: via requestPay (if > 0)
|
|
418
|
+
* - Fee Distribution:
|
|
419
|
+
* * 99.5% to seller (locked amount)
|
|
420
|
+
* * 0.5% + reward to staker (if applicable)
|
|
421
|
+
* - makeCaPay transfers from locked funds
|
|
422
|
+
*
|
|
423
|
+
* Ownership Transfer:
|
|
424
|
+
* - Changes identityDetails[username].owner
|
|
425
|
+
* - Preserves all metadata and expiration
|
|
426
|
+
* - Transfers all custom metadata slots
|
|
427
|
+
*
|
|
428
|
+
* Token Unlocking:
|
|
429
|
+
* - Decreases principalTokenTokenLockedForWithdrawOffers
|
|
430
|
+
* - Releases offer amount + marketplace fee
|
|
431
|
+
* - Distributes to seller and staker
|
|
432
|
+
*
|
|
433
|
+
* @param user Address of current username owner
|
|
452
434
|
* @param username Username being sold
|
|
453
|
-
* @param offerID Unique identifier of
|
|
454
|
-
* @param nonce
|
|
455
|
-
* @param signature Signature
|
|
456
|
-
* @param
|
|
457
|
-
* @param
|
|
458
|
-
* @param
|
|
459
|
-
* @param signature_EVVM Signature for the EVVM payment transaction
|
|
435
|
+
* @param offerID Unique identifier of offer to accept
|
|
436
|
+
* @param nonce Async nonce for replay protection
|
|
437
|
+
* @param signature Signature for Core.sol validation
|
|
438
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
439
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
440
|
+
* @param signaturePay Signature for EVVM payment
|
|
460
441
|
*/
|
|
461
442
|
function acceptOffer(
|
|
462
443
|
address user,
|
|
463
444
|
string memory username,
|
|
464
445
|
uint256 offerID,
|
|
446
|
+
address originExecutor,
|
|
465
447
|
uint256 nonce,
|
|
466
448
|
bytes memory signature,
|
|
467
|
-
uint256
|
|
468
|
-
uint256
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
449
|
+
uint256 priorityFeePay,
|
|
450
|
+
uint256 noncePay,
|
|
451
|
+
bytes memory signaturePay
|
|
452
|
+
) external {
|
|
453
|
+
core.validateAndConsumeNonce(
|
|
454
|
+
user,
|
|
455
|
+
Hash.hashDataForAcceptOffer(username, offerID),
|
|
456
|
+
originExecutor,
|
|
457
|
+
nonce,
|
|
458
|
+
true,
|
|
459
|
+
signature
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
if (identityDetails[username].owner != user)
|
|
463
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
464
|
+
|
|
472
465
|
if (
|
|
473
466
|
usernameOffers[username][offerID].offerer == address(0) ||
|
|
474
|
-
usernameOffers[username][offerID].
|
|
475
|
-
) revert
|
|
467
|
+
usernameOffers[username][offerID].expirationDate < block.timestamp
|
|
468
|
+
) revert Error.OfferInactive();
|
|
476
469
|
|
|
477
|
-
if (
|
|
478
|
-
|
|
479
|
-
IEvvm(evvmAddress.current).getEvvmID(),
|
|
480
|
-
user,
|
|
481
|
-
username,
|
|
482
|
-
offerID,
|
|
483
|
-
nonce,
|
|
484
|
-
signature
|
|
485
|
-
)
|
|
486
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
487
|
-
|
|
488
|
-
verifyAsyncNonce(user, nonce);
|
|
489
|
-
|
|
490
|
-
if (priorityFee_EVVM > 0) {
|
|
491
|
-
makePay(
|
|
492
|
-
user,
|
|
493
|
-
0,
|
|
494
|
-
priorityFee_EVVM,
|
|
495
|
-
nonce_EVVM,
|
|
496
|
-
priorityFlag_EVVM,
|
|
497
|
-
signature_EVVM
|
|
498
|
-
);
|
|
470
|
+
if (priorityFeePay > 0) {
|
|
471
|
+
requestPay(user, 0, priorityFeePay, noncePay, signaturePay);
|
|
499
472
|
}
|
|
500
473
|
|
|
501
474
|
makeCaPay(user, usernameOffers[username][offerID].amount);
|
|
@@ -505,161 +478,192 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
505
478
|
|
|
506
479
|
usernameOffers[username][offerID].offerer = address(0);
|
|
507
480
|
|
|
508
|
-
if (
|
|
481
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
509
482
|
makeCaPay(
|
|
510
483
|
msg.sender,
|
|
511
|
-
(
|
|
484
|
+
(core.getRewardAmount()) +
|
|
512
485
|
(((usernameOffers[username][offerID].amount * 1) / 199) /
|
|
513
486
|
4) +
|
|
514
|
-
|
|
487
|
+
priorityFeePay
|
|
515
488
|
);
|
|
516
489
|
}
|
|
517
490
|
|
|
518
491
|
principalTokenTokenLockedForWithdrawOffers -=
|
|
519
492
|
(usernameOffers[username][offerID].amount) +
|
|
520
493
|
(((usernameOffers[username][offerID].amount * 1) / 199) / 4);
|
|
521
|
-
|
|
522
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
523
494
|
}
|
|
524
495
|
|
|
525
496
|
/**
|
|
526
|
-
* @notice Renews
|
|
527
|
-
* @dev
|
|
497
|
+
* @notice Renews username registration for another year
|
|
498
|
+
* @dev Dynamic pricing based on timing and market demand
|
|
528
499
|
*
|
|
529
500
|
* Pricing Rules:
|
|
530
|
-
* - Free
|
|
531
|
-
* - Variable
|
|
532
|
-
* - Fixed 500,000
|
|
533
|
-
* - Can
|
|
501
|
+
* - Free: Renewed within grace period after expiration
|
|
502
|
+
* - Variable: Based on highest active offer (min 500 PT)
|
|
503
|
+
* - Fixed: 500,000 PT if renewed >1 year early
|
|
504
|
+
* - Can renew up to 100 years in advance
|
|
505
|
+
*
|
|
506
|
+
* Core.sol Integration:
|
|
507
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
508
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
509
|
+
* - Hash includes username only
|
|
510
|
+
* - Prevents replay attacks
|
|
511
|
+
*
|
|
512
|
+
* Core.sol Integration:
|
|
513
|
+
* - Payment: seePriceToRenew calculates cost
|
|
514
|
+
* - Paid through requestPay (locks tokens)
|
|
515
|
+
* - Staker reward: 1x reward + 50% of price + fee
|
|
516
|
+
* - makeCaPay distributes rewards
|
|
534
517
|
*
|
|
535
|
-
*
|
|
518
|
+
* Renewal Logic:
|
|
519
|
+
* - Extends expirationDate by 366 days
|
|
520
|
+
* - Preserves ownership and all metadata
|
|
521
|
+
* - Cannot exceed 100 years (36500 days)
|
|
522
|
+
*
|
|
523
|
+
* @param user Address of username owner
|
|
536
524
|
* @param username Username to renew
|
|
537
|
-
* @param nonce
|
|
538
|
-
* @param signature Signature
|
|
539
|
-
* @param
|
|
540
|
-
* @param
|
|
541
|
-
* @param
|
|
542
|
-
* @param signature_EVVM Signature for the EVVM payment transaction
|
|
525
|
+
* @param nonce Async nonce for replay protection
|
|
526
|
+
* @param signature Signature for Core.sol validation
|
|
527
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
528
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
529
|
+
* @param signaturePay Signature for EVVM payment
|
|
543
530
|
*/
|
|
544
531
|
function renewUsername(
|
|
545
532
|
address user,
|
|
546
533
|
string memory username,
|
|
534
|
+
address originExecutor,
|
|
547
535
|
uint256 nonce,
|
|
548
536
|
bytes memory signature,
|
|
549
|
-
uint256
|
|
550
|
-
uint256
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
537
|
+
uint256 priorityFeePay,
|
|
538
|
+
uint256 noncePay,
|
|
539
|
+
bytes memory signaturePay
|
|
540
|
+
) external {
|
|
541
|
+
core.validateAndConsumeNonce(
|
|
542
|
+
user,
|
|
543
|
+
Hash.hashDataForRenewUsername(username),
|
|
544
|
+
originExecutor,
|
|
545
|
+
nonce,
|
|
546
|
+
true,
|
|
547
|
+
signature
|
|
548
|
+
);
|
|
558
549
|
|
|
559
|
-
if (
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
nonce,
|
|
565
|
-
signature
|
|
566
|
-
)
|
|
567
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
550
|
+
if (identityDetails[username].owner != user)
|
|
551
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
552
|
+
|
|
553
|
+
if (identityDetails[username].flagNotAUsername == 0x01)
|
|
554
|
+
revert Error.IdentityIsNotAUsername();
|
|
568
555
|
|
|
569
|
-
|
|
556
|
+
if (
|
|
557
|
+
identityDetails[username].expirationDate >
|
|
558
|
+
block.timestamp + 36500 days
|
|
559
|
+
) revert Error.RenewalTimeLimitExceeded();
|
|
570
560
|
|
|
571
561
|
uint256 priceOfRenew = seePriceToRenew(username);
|
|
572
562
|
|
|
573
|
-
|
|
563
|
+
requestPay(
|
|
574
564
|
user,
|
|
575
565
|
priceOfRenew,
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
signature_EVVM
|
|
566
|
+
priorityFeePay,
|
|
567
|
+
noncePay,
|
|
568
|
+
signaturePay
|
|
580
569
|
);
|
|
581
570
|
|
|
582
|
-
if (
|
|
571
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
583
572
|
makeCaPay(
|
|
584
573
|
msg.sender,
|
|
585
|
-
|
|
574
|
+
core.getRewardAmount() +
|
|
586
575
|
((priceOfRenew * 50) / 100) +
|
|
587
|
-
|
|
576
|
+
priorityFeePay
|
|
588
577
|
);
|
|
589
578
|
}
|
|
590
579
|
|
|
591
|
-
identityDetails[username].
|
|
592
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
580
|
+
identityDetails[username].expirationDate += 366 days;
|
|
593
581
|
}
|
|
594
582
|
|
|
583
|
+
//█ Metadata Functions ████████████████████████████████████████████████████████████████████████
|
|
584
|
+
|
|
595
585
|
/**
|
|
596
|
-
* @notice Adds custom metadata to
|
|
597
|
-
* @dev Metadata
|
|
586
|
+
* @notice Adds custom metadata to username using schema format
|
|
587
|
+
* @dev Metadata format: [schema]:[subschema]>[value]
|
|
598
588
|
*
|
|
599
589
|
* Standard Format Examples:
|
|
600
590
|
* - memberOf:>EVVM
|
|
601
591
|
* - socialMedia:x>jistro (Twitter/X handle)
|
|
602
|
-
* - email:dev>jistro[at]evvm.org (
|
|
603
|
-
* - email:callme>contact[at]jistro.xyz (contact
|
|
592
|
+
* - email:dev>jistro[at]evvm.org (dev email)
|
|
593
|
+
* - email:callme>contact[at]jistro.xyz (contact)
|
|
604
594
|
*
|
|
605
595
|
* Schema Guidelines:
|
|
606
596
|
* - Based on https://schema.org/docs/schemas.html
|
|
607
597
|
* - ':' separates schema from subschema
|
|
608
598
|
* - '>' separates metadata from value
|
|
609
|
-
* - Pad
|
|
610
|
-
* - Use "socialMedia" for social networks
|
|
599
|
+
* - Pad spaces if schema/subschema < 5 chars
|
|
600
|
+
* - Use "socialMedia" for social networks
|
|
601
|
+
*
|
|
602
|
+
* Core.sol Integration:
|
|
603
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
604
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
605
|
+
* - Hash includes identity + value
|
|
606
|
+
* - Prevents replay attacks
|
|
607
|
+
*
|
|
608
|
+
* Core.sol Integration:
|
|
609
|
+
* - Payment: 10x EVVM reward amount
|
|
610
|
+
* - Paid through requestPay (locks tokens)
|
|
611
|
+
* - Staker reward: 5x reward + priority fee
|
|
612
|
+
* - makeCaPay distributes rewards
|
|
611
613
|
*
|
|
612
|
-
*
|
|
614
|
+
* Slot Management:
|
|
615
|
+
* - Increments customMetadataMaxSlots
|
|
616
|
+
* - Each slot holds one metadata entry
|
|
617
|
+
* - No limit on number of slots
|
|
618
|
+
*
|
|
619
|
+
* @param user Address of username owner
|
|
613
620
|
* @param identity Username to add metadata to
|
|
614
|
-
* @param value Metadata string following
|
|
615
|
-
* @param nonce
|
|
616
|
-
* @param signature Signature
|
|
617
|
-
* @param
|
|
618
|
-
* @param
|
|
619
|
-
* @param
|
|
620
|
-
* @param signature_EVVM Signature for the EVVM payment transaction
|
|
621
|
+
* @param value Metadata string following format
|
|
622
|
+
* @param nonce Async nonce for replay protection
|
|
623
|
+
* @param signature Signature for Core.sol validation
|
|
624
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
625
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
626
|
+
* @param signaturePay Signature for EVVM payment
|
|
621
627
|
*/
|
|
622
628
|
function addCustomMetadata(
|
|
623
629
|
address user,
|
|
624
630
|
string memory identity,
|
|
625
631
|
string memory value,
|
|
632
|
+
address originExecutor,
|
|
626
633
|
uint256 nonce,
|
|
627
634
|
bytes memory signature,
|
|
628
|
-
uint256
|
|
629
|
-
uint256
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
635
|
+
uint256 priorityFeePay,
|
|
636
|
+
uint256 noncePay,
|
|
637
|
+
bytes memory signaturePay
|
|
638
|
+
) external {
|
|
639
|
+
core.validateAndConsumeNonce(
|
|
640
|
+
user,
|
|
641
|
+
Hash.hashDataForAddCustomMetadata(identity, value),
|
|
642
|
+
originExecutor,
|
|
643
|
+
nonce,
|
|
644
|
+
true,
|
|
645
|
+
signature
|
|
646
|
+
);
|
|
634
647
|
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
IEvvm(evvmAddress.current).getEvvmID(),
|
|
638
|
-
user,
|
|
639
|
-
identity,
|
|
640
|
-
value,
|
|
641
|
-
nonce,
|
|
642
|
-
signature
|
|
643
|
-
)
|
|
644
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
648
|
+
if (identityDetails[identity].owner != user)
|
|
649
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
645
650
|
|
|
646
|
-
|
|
651
|
+
if (bytes(value).length == 0) revert Error.EmptyCustomMetadata();
|
|
647
652
|
|
|
648
|
-
|
|
653
|
+
requestPay(
|
|
649
654
|
user,
|
|
650
655
|
getPriceToAddCustomMetadata(),
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
signature_EVVM
|
|
656
|
+
priorityFeePay,
|
|
657
|
+
noncePay,
|
|
658
|
+
signaturePay
|
|
655
659
|
);
|
|
656
660
|
|
|
657
|
-
if (
|
|
661
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
658
662
|
makeCaPay(
|
|
659
663
|
msg.sender,
|
|
660
|
-
(5 *
|
|
664
|
+
(5 * core.getRewardAmount()) +
|
|
661
665
|
((getPriceToAddCustomMetadata() * 50) / 100) +
|
|
662
|
-
|
|
666
|
+
priorityFeePay
|
|
663
667
|
);
|
|
664
668
|
}
|
|
665
669
|
|
|
@@ -668,56 +672,77 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
668
672
|
] = value;
|
|
669
673
|
|
|
670
674
|
identityDetails[identity].customMetadataMaxSlots++;
|
|
671
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
672
675
|
}
|
|
673
676
|
|
|
674
677
|
/**
|
|
675
|
-
* @notice Removes
|
|
676
|
-
* @dev Shifts all subsequent
|
|
677
|
-
*
|
|
678
|
+
* @notice Removes specific custom metadata entry by key
|
|
679
|
+
* @dev Shifts all subsequent entries to fill gap
|
|
680
|
+
*
|
|
681
|
+
* Removal Process:
|
|
682
|
+
* 1. Validates user owns username
|
|
683
|
+
* 2. Validates key exists in metadata slots
|
|
684
|
+
* 3. Deletes entry at key position
|
|
685
|
+
* 4. Shifts all entries after key down by 1
|
|
686
|
+
* 5. Decrements customMetadataMaxSlots
|
|
687
|
+
*
|
|
688
|
+
* Core.sol Integration:
|
|
689
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
690
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
691
|
+
* - Hash includes identity + key
|
|
692
|
+
* - Prevents replay attacks
|
|
693
|
+
*
|
|
694
|
+
* Core.sol Integration:
|
|
695
|
+
* - Payment: 10x EVVM reward amount
|
|
696
|
+
* - Paid through requestPay (locks tokens)
|
|
697
|
+
* - Staker reward: 5x reward + priority fee
|
|
698
|
+
* - makeCaPay distributes rewards
|
|
699
|
+
*
|
|
700
|
+
* Array Reordering:
|
|
701
|
+
* - Shifts entries from key+1 to maxSlots
|
|
702
|
+
* - Maintains continuous slot indexing
|
|
703
|
+
* - No gaps in metadata array
|
|
704
|
+
*
|
|
705
|
+
* @param user Address of username owner
|
|
678
706
|
* @param identity Username to remove metadata from
|
|
679
|
-
* @param key Index of
|
|
680
|
-
* @param nonce
|
|
681
|
-
* @param signature Signature
|
|
682
|
-
* @param
|
|
683
|
-
* @param
|
|
684
|
-
* @param
|
|
685
|
-
* @param signature_EVVM Signature for the EVVM payment transaction
|
|
707
|
+
* @param key Index of metadata entry to remove
|
|
708
|
+
* @param nonce Async nonce for replay protection
|
|
709
|
+
* @param signature Signature for Core.sol validation
|
|
710
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
711
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
712
|
+
* @param signaturePay Signature for EVVM payment
|
|
686
713
|
*/
|
|
687
714
|
function removeCustomMetadata(
|
|
688
715
|
address user,
|
|
689
716
|
string memory identity,
|
|
690
717
|
uint256 key,
|
|
718
|
+
address originExecutor,
|
|
691
719
|
uint256 nonce,
|
|
692
720
|
bytes memory signature,
|
|
693
|
-
uint256
|
|
694
|
-
uint256
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
signature
|
|
706
|
-
)
|
|
707
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
721
|
+
uint256 priorityFeePay,
|
|
722
|
+
uint256 noncePay,
|
|
723
|
+
bytes memory signaturePay
|
|
724
|
+
) external {
|
|
725
|
+
core.validateAndConsumeNonce(
|
|
726
|
+
user,
|
|
727
|
+
Hash.hashDataForRemoveCustomMetadata(identity, key),
|
|
728
|
+
originExecutor,
|
|
729
|
+
nonce,
|
|
730
|
+
true,
|
|
731
|
+
signature
|
|
732
|
+
);
|
|
708
733
|
|
|
709
|
-
|
|
734
|
+
if (identityDetails[identity].owner != user)
|
|
735
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
710
736
|
|
|
711
737
|
if (identityDetails[identity].customMetadataMaxSlots <= key)
|
|
712
|
-
revert
|
|
738
|
+
revert Error.InvalidKey();
|
|
713
739
|
|
|
714
|
-
|
|
740
|
+
requestPay(
|
|
715
741
|
user,
|
|
716
742
|
getPriceToRemoveCustomMetadata(),
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
signature_EVVM
|
|
743
|
+
priorityFeePay,
|
|
744
|
+
noncePay,
|
|
745
|
+
signaturePay
|
|
721
746
|
);
|
|
722
747
|
|
|
723
748
|
if (identityDetails[identity].customMetadataMaxSlots == key) {
|
|
@@ -736,61 +761,84 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
736
761
|
identityDetails[identity].customMetadataMaxSlots
|
|
737
762
|
];
|
|
738
763
|
}
|
|
764
|
+
|
|
739
765
|
identityDetails[identity].customMetadataMaxSlots--;
|
|
740
|
-
|
|
741
|
-
if (
|
|
766
|
+
|
|
767
|
+
if (core.isAddressStaker(msg.sender))
|
|
742
768
|
makeCaPay(
|
|
743
769
|
msg.sender,
|
|
744
|
-
(5 *
|
|
745
|
-
priorityFee_EVVM
|
|
770
|
+
(5 * core.getRewardAmount()) + priorityFeePay
|
|
746
771
|
);
|
|
747
|
-
}
|
|
748
772
|
}
|
|
749
773
|
|
|
750
774
|
/**
|
|
751
|
-
* @notice Removes all custom metadata entries for
|
|
752
|
-
* @dev More gas-efficient than removing
|
|
753
|
-
*
|
|
775
|
+
* @notice Removes all custom metadata entries for username
|
|
776
|
+
* @dev More gas-efficient than removing individually
|
|
777
|
+
*
|
|
778
|
+
* Flush Process:
|
|
779
|
+
* 1. Validates user owns username
|
|
780
|
+
* 2. Validates metadata slots exist (not empty)
|
|
781
|
+
* 3. Calculates cost based on slot count
|
|
782
|
+
* 4. Deletes all metadata entries in loop
|
|
783
|
+
* 5. Resets customMetadataMaxSlots to 0
|
|
784
|
+
*
|
|
785
|
+
* Core.sol Integration:
|
|
786
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
787
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
788
|
+
* - Hash includes identity only
|
|
789
|
+
* - Prevents replay attacks
|
|
790
|
+
*
|
|
791
|
+
* Core.sol Integration:
|
|
792
|
+
* - Payment: getPriceToFlushCustomMetadata (per slot)
|
|
793
|
+
* - Cost: 10x EVVM reward per metadata entry
|
|
794
|
+
* - Paid through requestPay (locks tokens)
|
|
795
|
+
* - Staker reward: 5x reward per slot + priority
|
|
796
|
+
* - makeCaPay distributes batch rewards
|
|
797
|
+
*
|
|
798
|
+
* Efficiency:
|
|
799
|
+
* - Single transaction for all metadata
|
|
800
|
+
* - Batch pricing for multiple entries
|
|
801
|
+
* - Cheaper than calling removeCustomMetadata N times
|
|
802
|
+
*
|
|
803
|
+
* @param user Address of username owner
|
|
754
804
|
* @param identity Username to flush all metadata from
|
|
755
|
-
* @param nonce
|
|
756
|
-
* @param signature Signature
|
|
757
|
-
* @param
|
|
758
|
-
* @param
|
|
759
|
-
* @param
|
|
760
|
-
* @param signature_EVVM Signature for the EVVM payment transaction
|
|
805
|
+
* @param nonce Async nonce for replay protection
|
|
806
|
+
* @param signature Signature for Core.sol validation
|
|
807
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
808
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
809
|
+
* @param signaturePay Signature for EVVM payment
|
|
761
810
|
*/
|
|
762
811
|
function flushCustomMetadata(
|
|
763
812
|
address user,
|
|
764
813
|
string memory identity,
|
|
814
|
+
address originExecutor,
|
|
765
815
|
uint256 nonce,
|
|
766
816
|
bytes memory signature,
|
|
767
|
-
uint256
|
|
768
|
-
uint256
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
)
|
|
780
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
817
|
+
uint256 priorityFeePay,
|
|
818
|
+
uint256 noncePay,
|
|
819
|
+
bytes memory signaturePay
|
|
820
|
+
) external {
|
|
821
|
+
core.validateAndConsumeNonce(
|
|
822
|
+
user,
|
|
823
|
+
Hash.hashDataForFlushCustomMetadata(identity),
|
|
824
|
+
originExecutor,
|
|
825
|
+
nonce,
|
|
826
|
+
true,
|
|
827
|
+
signature
|
|
828
|
+
);
|
|
781
829
|
|
|
782
|
-
|
|
830
|
+
if (identityDetails[identity].owner != user)
|
|
831
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
783
832
|
|
|
784
833
|
if (identityDetails[identity].customMetadataMaxSlots == 0)
|
|
785
|
-
revert
|
|
834
|
+
revert Error.EmptyCustomMetadata();
|
|
786
835
|
|
|
787
|
-
|
|
836
|
+
requestPay(
|
|
788
837
|
user,
|
|
789
838
|
getPriceToFlushCustomMetadata(identity),
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
signature_EVVM
|
|
839
|
+
priorityFeePay,
|
|
840
|
+
noncePay,
|
|
841
|
+
signaturePay
|
|
794
842
|
);
|
|
795
843
|
|
|
796
844
|
for (
|
|
@@ -801,65 +849,96 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
801
849
|
delete identityCustomMetadata[identity][i];
|
|
802
850
|
}
|
|
803
851
|
|
|
804
|
-
if (
|
|
852
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
805
853
|
makeCaPay(
|
|
806
854
|
msg.sender,
|
|
807
|
-
((5 *
|
|
855
|
+
((5 * core.getRewardAmount()) *
|
|
808
856
|
identityDetails[identity].customMetadataMaxSlots) +
|
|
809
|
-
|
|
857
|
+
priorityFeePay
|
|
810
858
|
);
|
|
811
859
|
}
|
|
812
860
|
|
|
813
861
|
identityDetails[identity].customMetadataMaxSlots = 0;
|
|
814
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
815
862
|
}
|
|
816
863
|
|
|
817
864
|
/**
|
|
818
|
-
* @notice Completely removes
|
|
819
|
-
* @dev Deletes
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
865
|
+
* @notice Completely removes username and all data
|
|
866
|
+
* @dev Deletes username, metadata, makes available for
|
|
867
|
+
* re-registration
|
|
868
|
+
*
|
|
869
|
+
* Flush Process:
|
|
870
|
+
* 1. Validates user owns username
|
|
871
|
+
* 2. Validates not expired (must be active)
|
|
872
|
+
* 3. Validates is actual username (not temp hash)
|
|
873
|
+
* 4. Calculates cost based on metadata + username
|
|
874
|
+
* 5. Deletes all metadata entries
|
|
875
|
+
* 6. Resets username to default state
|
|
876
|
+
* 7. Preserves offerMaxSlots history
|
|
877
|
+
*
|
|
878
|
+
* Core.sol Integration:
|
|
879
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
880
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
881
|
+
* - Hash includes username only
|
|
882
|
+
* - Prevents replay attacks
|
|
883
|
+
*
|
|
884
|
+
* Core.sol Integration:
|
|
885
|
+
* - Payment: getPriceToFlushUsername
|
|
886
|
+
* - Cost: Base + (10x reward per metadata slot)
|
|
887
|
+
* - Paid through requestPay (locks tokens)
|
|
888
|
+
* - Staker reward: 5x reward per slot + priority
|
|
889
|
+
* - makeCaPay distributes to caller
|
|
890
|
+
*
|
|
891
|
+
* Cleanup:
|
|
892
|
+
* - Deletes all custom metadata slots
|
|
893
|
+
* - Sets owner to address(0)
|
|
894
|
+
* - Sets expirationDate to 0
|
|
895
|
+
* - Resets customMetadataMaxSlots to 0
|
|
896
|
+
* - Keeps offerMaxSlots for history
|
|
897
|
+
* - Sets flagNotAUsername to 0x00
|
|
898
|
+
* - Username becomes available for re-registration
|
|
899
|
+
*
|
|
900
|
+
* @param user Address of username owner
|
|
901
|
+
* @param username Username to completely remove
|
|
902
|
+
* @param nonce Async nonce for replay protection
|
|
903
|
+
* @param signature Signature for Core.sol validation
|
|
904
|
+
* @param priorityFeePay Priority fee for faster processing
|
|
905
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
906
|
+
* @param signaturePay Signature for EVVM payment
|
|
828
907
|
*/
|
|
829
908
|
function flushUsername(
|
|
830
909
|
address user,
|
|
831
910
|
string memory username,
|
|
911
|
+
address originExecutor,
|
|
832
912
|
uint256 nonce,
|
|
833
913
|
bytes memory signature,
|
|
834
|
-
uint256
|
|
835
|
-
uint256
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
914
|
+
uint256 priorityFeePay,
|
|
915
|
+
uint256 noncePay,
|
|
916
|
+
bytes memory signaturePay
|
|
917
|
+
) external {
|
|
918
|
+
core.validateAndConsumeNonce(
|
|
919
|
+
user,
|
|
920
|
+
Hash.hashDataForFlushUsername(username),
|
|
921
|
+
originExecutor,
|
|
922
|
+
nonce,
|
|
923
|
+
true,
|
|
924
|
+
signature
|
|
925
|
+
);
|
|
843
926
|
|
|
844
|
-
if (
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
nonce,
|
|
850
|
-
signature
|
|
851
|
-
)
|
|
852
|
-
) revert ErrorsLib.InvalidSignatureOnNameService();
|
|
927
|
+
if (identityDetails[username].owner != user)
|
|
928
|
+
revert Error.UserIsNotOwnerOfIdentity();
|
|
929
|
+
|
|
930
|
+
if (block.timestamp >= identityDetails[username].expirationDate)
|
|
931
|
+
revert Error.OwnershipExpired();
|
|
853
932
|
|
|
854
|
-
|
|
933
|
+
if (identityDetails[username].flagNotAUsername == 0x01)
|
|
934
|
+
revert Error.IdentityIsNotAUsername();
|
|
855
935
|
|
|
856
|
-
|
|
936
|
+
requestPay(
|
|
857
937
|
user,
|
|
858
938
|
getPriceToFlushUsername(username),
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
signature_EVVM
|
|
939
|
+
priorityFeePay,
|
|
940
|
+
noncePay,
|
|
941
|
+
signaturePay
|
|
863
942
|
);
|
|
864
943
|
|
|
865
944
|
for (
|
|
@@ -872,32 +951,30 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
872
951
|
|
|
873
952
|
makeCaPay(
|
|
874
953
|
msg.sender,
|
|
875
|
-
((5 *
|
|
954
|
+
((5 * core.getRewardAmount()) *
|
|
876
955
|
identityDetails[username].customMetadataMaxSlots) +
|
|
877
|
-
|
|
956
|
+
priorityFeePay
|
|
878
957
|
);
|
|
879
958
|
|
|
880
|
-
identityDetails[username] = IdentityBaseMetadata({
|
|
959
|
+
identityDetails[username] = Structs.IdentityBaseMetadata({
|
|
881
960
|
owner: address(0),
|
|
882
|
-
|
|
961
|
+
expirationDate: 0,
|
|
883
962
|
customMetadataMaxSlots: 0,
|
|
884
963
|
offerMaxSlots: identityDetails[username].offerMaxSlots,
|
|
885
964
|
flagNotAUsername: 0x00
|
|
886
965
|
});
|
|
887
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
888
966
|
}
|
|
889
967
|
|
|
890
|
-
//█ Administrative Functions
|
|
968
|
+
//█ Administrative Functions ████████████████████████████████████████████████████████████████████████
|
|
891
969
|
|
|
892
970
|
/**
|
|
893
|
-
* @notice Proposes
|
|
894
|
-
* @dev
|
|
971
|
+
* @notice Proposes new admin address with 1-day delay
|
|
972
|
+
* @dev Time-delayed governance system for admin changes
|
|
895
973
|
* @param _adminToPropose Address of the proposed new admin
|
|
896
974
|
*/
|
|
897
975
|
function proposeAdmin(address _adminToPropose) public onlyAdmin {
|
|
898
|
-
if (_adminToPropose == address(0) || _adminToPropose == admin.current)
|
|
899
|
-
revert();
|
|
900
|
-
}
|
|
976
|
+
if (_adminToPropose == address(0) || _adminToPropose == admin.current)
|
|
977
|
+
revert Error.InvalidAdminProposal();
|
|
901
978
|
|
|
902
979
|
admin.proposal = _adminToPropose;
|
|
903
980
|
admin.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
|
|
@@ -917,14 +994,13 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
917
994
|
* @dev Can only be called by the proposed admin after the time delay has passed
|
|
918
995
|
*/
|
|
919
996
|
function acceptProposeAdmin() public {
|
|
920
|
-
if (admin.proposal != msg.sender)
|
|
921
|
-
revert();
|
|
922
|
-
|
|
923
|
-
if (block.timestamp < admin.timeToAccept)
|
|
924
|
-
revert();
|
|
925
|
-
}
|
|
997
|
+
if (admin.proposal != msg.sender)
|
|
998
|
+
revert Error.SenderIsNotProposedAdmin();
|
|
999
|
+
|
|
1000
|
+
if (block.timestamp < admin.timeToAccept)
|
|
1001
|
+
revert Error.LockTimeNotExpired();
|
|
926
1002
|
|
|
927
|
-
admin = AddressTypeProposal({
|
|
1003
|
+
admin = ProposalStructs.AddressTypeProposal({
|
|
928
1004
|
current: admin.proposal,
|
|
929
1005
|
proposal: address(0),
|
|
930
1006
|
timeToAccept: 0
|
|
@@ -938,17 +1014,14 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
938
1014
|
*/
|
|
939
1015
|
function proposeWithdrawPrincipalTokens(uint256 _amount) public onlyAdmin {
|
|
940
1016
|
if (
|
|
941
|
-
|
|
942
|
-
address(this),
|
|
943
|
-
PRINCIPAL_TOKEN_ADDRESS
|
|
944
|
-
) -
|
|
1017
|
+
core.getBalance(address(this), core.getPrincipalTokenAddress()) -
|
|
945
1018
|
(5083 +
|
|
946
|
-
|
|
1019
|
+
core.getRewardAmount() +
|
|
947
1020
|
principalTokenTokenLockedForWithdrawOffers) <
|
|
948
1021
|
_amount ||
|
|
949
1022
|
_amount == 0
|
|
950
1023
|
) {
|
|
951
|
-
revert();
|
|
1024
|
+
revert Error.InvalidWithdrawAmount();
|
|
952
1025
|
}
|
|
953
1026
|
|
|
954
1027
|
amountToWithdrawTokens.proposal = _amount;
|
|
@@ -971,9 +1044,8 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
971
1044
|
* @dev Can only be called after the time delay has passed
|
|
972
1045
|
*/
|
|
973
1046
|
function claimWithdrawPrincipalTokens() public onlyAdmin {
|
|
974
|
-
if (block.timestamp < amountToWithdrawTokens.timeToAccept)
|
|
975
|
-
revert();
|
|
976
|
-
}
|
|
1047
|
+
if (block.timestamp < amountToWithdrawTokens.timeToAccept)
|
|
1048
|
+
revert Error.LockTimeNotExpired();
|
|
977
1049
|
|
|
978
1050
|
makeCaPay(admin.current, amountToWithdrawTokens.proposal);
|
|
979
1051
|
|
|
@@ -989,11 +1061,10 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
989
1061
|
function proposeChangeEvvmAddress(
|
|
990
1062
|
address _newEvvmAddress
|
|
991
1063
|
) public onlyAdmin {
|
|
992
|
-
if (_newEvvmAddress == address(0))
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
evvmAddress.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
|
|
1064
|
+
if (_newEvvmAddress == address(0)) revert Error.InvalidEvvmAddress();
|
|
1065
|
+
|
|
1066
|
+
coreAddress.proposal = _newEvvmAddress;
|
|
1067
|
+
coreAddress.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
|
|
997
1068
|
}
|
|
998
1069
|
|
|
999
1070
|
/**
|
|
@@ -1001,8 +1072,8 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1001
1072
|
* @dev Only the current admin can cancel pending proposals
|
|
1002
1073
|
*/
|
|
1003
1074
|
function cancelChangeEvvmAddress() public onlyAdmin {
|
|
1004
|
-
|
|
1005
|
-
|
|
1075
|
+
coreAddress.proposal = address(0);
|
|
1076
|
+
coreAddress.timeToAccept = 0;
|
|
1006
1077
|
}
|
|
1007
1078
|
|
|
1008
1079
|
/**
|
|
@@ -1010,16 +1081,16 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1010
1081
|
* @dev Can only be called after the time delay has passed
|
|
1011
1082
|
*/
|
|
1012
1083
|
function acceptChangeEvvmAddress() public onlyAdmin {
|
|
1013
|
-
if (block.timestamp <
|
|
1014
|
-
revert();
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
current:
|
|
1084
|
+
if (block.timestamp < coreAddress.timeToAccept)
|
|
1085
|
+
revert Error.LockTimeNotExpired();
|
|
1086
|
+
|
|
1087
|
+
coreAddress = ProposalStructs.AddressTypeProposal({
|
|
1088
|
+
current: coreAddress.proposal,
|
|
1018
1089
|
proposal: address(0),
|
|
1019
1090
|
timeToAccept: 0
|
|
1020
1091
|
});
|
|
1021
1092
|
|
|
1022
|
-
|
|
1093
|
+
core = Core(coreAddress.current);
|
|
1023
1094
|
}
|
|
1024
1095
|
|
|
1025
1096
|
//█ Utility Functions ████████████████████████████████████████████████████████████████████████
|
|
@@ -1033,27 +1104,26 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1033
1104
|
* @param amount Amount to pay in Principal Tokens
|
|
1034
1105
|
* @param priorityFee Additional priority fee for faster processing
|
|
1035
1106
|
* @param nonce Nonce for the EVVM transaction
|
|
1036
|
-
* @param priorityFlag True for async payment, false for sync payment
|
|
1037
1107
|
* @param signature Signature authorizing the payment
|
|
1108
|
+
* @dev all evvm nonce execution are async (true)
|
|
1038
1109
|
*/
|
|
1039
|
-
function
|
|
1110
|
+
function requestPay(
|
|
1040
1111
|
address user,
|
|
1041
1112
|
uint256 amount,
|
|
1042
1113
|
uint256 priorityFee,
|
|
1043
1114
|
uint256 nonce,
|
|
1044
|
-
bool priorityFlag,
|
|
1045
1115
|
bytes memory signature
|
|
1046
1116
|
) internal {
|
|
1047
|
-
|
|
1117
|
+
core.pay(
|
|
1048
1118
|
user,
|
|
1049
1119
|
address(this),
|
|
1050
1120
|
"",
|
|
1051
|
-
|
|
1121
|
+
core.getPrincipalTokenAddress(),
|
|
1052
1122
|
amount,
|
|
1053
1123
|
priorityFee,
|
|
1054
|
-
nonce,
|
|
1055
|
-
priorityFlag,
|
|
1056
1124
|
address(this),
|
|
1125
|
+
nonce,
|
|
1126
|
+
true,
|
|
1057
1127
|
signature
|
|
1058
1128
|
);
|
|
1059
1129
|
}
|
|
@@ -1065,7 +1135,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1065
1135
|
* @param amount Amount of Principal Tokens to distribute
|
|
1066
1136
|
*/
|
|
1067
1137
|
function makeCaPay(address user, uint256 amount) internal {
|
|
1068
|
-
|
|
1138
|
+
core.caPay(user, core.getPrincipalTokenAddress(), amount);
|
|
1069
1139
|
}
|
|
1070
1140
|
|
|
1071
1141
|
//█ Username Hashing Functions ███████████████████████████████████████████████████████████████████
|
|
@@ -1100,14 +1170,14 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1100
1170
|
if (identityDetails[_identity].flagNotAUsername == 0x01) {
|
|
1101
1171
|
if (
|
|
1102
1172
|
identityDetails[_identity].owner == address(0) ||
|
|
1103
|
-
identityDetails[_identity].
|
|
1173
|
+
identityDetails[_identity].expirationDate != 0
|
|
1104
1174
|
) {
|
|
1105
1175
|
return false;
|
|
1106
1176
|
} else {
|
|
1107
1177
|
return true;
|
|
1108
1178
|
}
|
|
1109
1179
|
} else {
|
|
1110
|
-
if (identityDetails[_identity].
|
|
1180
|
+
if (identityDetails[_identity].expirationDate == 0) {
|
|
1111
1181
|
return false;
|
|
1112
1182
|
} else {
|
|
1113
1183
|
return true;
|
|
@@ -1127,14 +1197,14 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1127
1197
|
if (identityDetails[_username].flagNotAUsername == 0x01) {
|
|
1128
1198
|
if (
|
|
1129
1199
|
identityDetails[_username].owner == address(0) ||
|
|
1130
|
-
identityDetails[_username].
|
|
1200
|
+
identityDetails[_username].expirationDate != 0
|
|
1131
1201
|
) {
|
|
1132
1202
|
revert();
|
|
1133
1203
|
} else {
|
|
1134
1204
|
return true;
|
|
1135
1205
|
}
|
|
1136
1206
|
} else {
|
|
1137
|
-
if (identityDetails[_username].
|
|
1207
|
+
if (identityDetails[_username].expirationDate == 0) {
|
|
1138
1208
|
revert();
|
|
1139
1209
|
} else {
|
|
1140
1210
|
return true;
|
|
@@ -1163,9 +1233,8 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1163
1233
|
function verifyStrictAndGetOwnerOfIdentity(
|
|
1164
1234
|
string memory _username
|
|
1165
1235
|
) public view returns (address answer) {
|
|
1166
|
-
if (strictVerifyIfIdentityExist(_username))
|
|
1236
|
+
if (strictVerifyIfIdentityExist(_username))
|
|
1167
1237
|
answer = identityDetails[_username].owner;
|
|
1168
|
-
}
|
|
1169
1238
|
}
|
|
1170
1239
|
|
|
1171
1240
|
/**
|
|
@@ -1180,15 +1249,15 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1180
1249
|
function seePriceToRenew(
|
|
1181
1250
|
string memory _identity
|
|
1182
1251
|
) public view returns (uint256 price) {
|
|
1183
|
-
if (identityDetails[_identity].
|
|
1184
|
-
if (usernameOffers[_identity][0].
|
|
1252
|
+
if (identityDetails[_identity].expirationDate >= block.timestamp) {
|
|
1253
|
+
if (usernameOffers[_identity][0].expirationDate != 0) {
|
|
1185
1254
|
for (
|
|
1186
1255
|
uint256 i = 0;
|
|
1187
1256
|
i < identityDetails[_identity].offerMaxSlots;
|
|
1188
1257
|
i++
|
|
1189
1258
|
) {
|
|
1190
1259
|
if (
|
|
1191
|
-
usernameOffers[_identity][i].
|
|
1260
|
+
usernameOffers[_identity][i].expirationDate >
|
|
1192
1261
|
block.timestamp &&
|
|
1193
1262
|
usernameOffers[_identity][i].offerer != address(0)
|
|
1194
1263
|
) {
|
|
@@ -1201,14 +1270,14 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1201
1270
|
if (price == 0) {
|
|
1202
1271
|
price = 500 * 10 ** 18;
|
|
1203
1272
|
} else {
|
|
1204
|
-
uint256 principalTokenReward =
|
|
1205
|
-
|
|
1273
|
+
uint256 principalTokenReward = core.getRewardAmount();
|
|
1274
|
+
|
|
1206
1275
|
price = ((price * 5) / 1000) > (500000 * principalTokenReward)
|
|
1207
1276
|
? (500000 * principalTokenReward)
|
|
1208
1277
|
: ((price * 5) / 1000);
|
|
1209
1278
|
}
|
|
1210
1279
|
} else {
|
|
1211
|
-
price = 500_000 *
|
|
1280
|
+
price = 500_000 * core.getRewardAmount();
|
|
1212
1281
|
}
|
|
1213
1282
|
}
|
|
1214
1283
|
|
|
@@ -1218,7 +1287,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1218
1287
|
* @return price Cost in Principal Tokens (10x current reward amount)
|
|
1219
1288
|
*/
|
|
1220
1289
|
function getPriceToAddCustomMetadata() public view returns (uint256 price) {
|
|
1221
|
-
price = 10 *
|
|
1290
|
+
price = 10 * core.getRewardAmount();
|
|
1222
1291
|
}
|
|
1223
1292
|
|
|
1224
1293
|
/**
|
|
@@ -1231,7 +1300,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1231
1300
|
view
|
|
1232
1301
|
returns (uint256 price)
|
|
1233
1302
|
{
|
|
1234
|
-
price = 10 *
|
|
1303
|
+
price = 10 * core.getRewardAmount();
|
|
1235
1304
|
}
|
|
1236
1305
|
|
|
1237
1306
|
/**
|
|
@@ -1244,7 +1313,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1244
1313
|
string memory _identity
|
|
1245
1314
|
) public view returns (uint256 price) {
|
|
1246
1315
|
price =
|
|
1247
|
-
(10 *
|
|
1316
|
+
(10 * core.getRewardAmount()) *
|
|
1248
1317
|
identityDetails[_identity].customMetadataMaxSlots;
|
|
1249
1318
|
}
|
|
1250
1319
|
|
|
@@ -1258,9 +1327,9 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1258
1327
|
string memory _identity
|
|
1259
1328
|
) public view returns (uint256 price) {
|
|
1260
1329
|
price =
|
|
1261
|
-
((10 *
|
|
1330
|
+
((10 * core.getRewardAmount()) *
|
|
1262
1331
|
identityDetails[_identity].customMetadataMaxSlots) +
|
|
1263
|
-
|
|
1332
|
+
core.getRewardAmount();
|
|
1264
1333
|
}
|
|
1265
1334
|
|
|
1266
1335
|
//█ Identity Availability Functions ██████████████████████████████████████████████████████████████
|
|
@@ -1274,11 +1343,11 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1274
1343
|
function isUsernameAvailable(
|
|
1275
1344
|
string memory _username
|
|
1276
1345
|
) public view returns (bool) {
|
|
1277
|
-
if (identityDetails[_username].
|
|
1346
|
+
if (identityDetails[_username].expirationDate == 0) {
|
|
1278
1347
|
return true;
|
|
1279
1348
|
} else {
|
|
1280
1349
|
return
|
|
1281
|
-
identityDetails[_username].
|
|
1350
|
+
identityDetails[_username].expirationDate + 60 days <
|
|
1282
1351
|
block.timestamp;
|
|
1283
1352
|
}
|
|
1284
1353
|
}
|
|
@@ -1294,7 +1363,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1294
1363
|
) public view returns (address, uint256) {
|
|
1295
1364
|
return (
|
|
1296
1365
|
identityDetails[_username].owner,
|
|
1297
|
-
identityDetails[_username].
|
|
1366
|
+
identityDetails[_username].expirationDate
|
|
1298
1367
|
);
|
|
1299
1368
|
}
|
|
1300
1369
|
|
|
@@ -1368,8 +1437,10 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1368
1437
|
*/
|
|
1369
1438
|
function getOffersOfUsername(
|
|
1370
1439
|
string memory _username
|
|
1371
|
-
) public view returns (OfferMetadata[] memory offers) {
|
|
1372
|
-
offers = new OfferMetadata[](
|
|
1440
|
+
) public view returns (Structs.OfferMetadata[] memory offers) {
|
|
1441
|
+
offers = new Structs.OfferMetadata[](
|
|
1442
|
+
identityDetails[_username].offerMaxSlots
|
|
1443
|
+
);
|
|
1373
1444
|
|
|
1374
1445
|
for (uint256 i = 0; i < identityDetails[_username].offerMaxSlots; i++) {
|
|
1375
1446
|
offers[i] = usernameOffers[_username][i];
|
|
@@ -1386,7 +1457,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1386
1457
|
function getSingleOfferOfUsername(
|
|
1387
1458
|
string memory _username,
|
|
1388
1459
|
uint256 _offerID
|
|
1389
|
-
) public view returns (OfferMetadata memory offer) {
|
|
1460
|
+
) public view returns (Structs.OfferMetadata memory offer) {
|
|
1390
1461
|
return usernameOffers[_username][_offerID];
|
|
1391
1462
|
}
|
|
1392
1463
|
|
|
@@ -1401,7 +1472,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1401
1472
|
) public view returns (uint256 length) {
|
|
1402
1473
|
do {
|
|
1403
1474
|
length++;
|
|
1404
|
-
} while (usernameOffers[_username][length].
|
|
1475
|
+
} while (usernameOffers[_username][length].expirationDate != 0);
|
|
1405
1476
|
}
|
|
1406
1477
|
|
|
1407
1478
|
/**
|
|
@@ -1413,7 +1484,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1413
1484
|
function getExpireDateOfIdentity(
|
|
1414
1485
|
string memory _identity
|
|
1415
1486
|
) public view returns (uint256) {
|
|
1416
|
-
return identityDetails[_identity].
|
|
1487
|
+
return identityDetails[_identity].expirationDate;
|
|
1417
1488
|
}
|
|
1418
1489
|
|
|
1419
1490
|
/**
|
|
@@ -1430,7 +1501,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1430
1501
|
return
|
|
1431
1502
|
identityDetails[username].offerMaxSlots > 0
|
|
1432
1503
|
? seePriceToRenew(username)
|
|
1433
|
-
:
|
|
1504
|
+
: core.getRewardAmount() * 100;
|
|
1434
1505
|
}
|
|
1435
1506
|
|
|
1436
1507
|
//█ Administrative Getters ███████████████████████████████████████████████████████████████████████
|
|
@@ -1483,13 +1554,22 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1483
1554
|
);
|
|
1484
1555
|
}
|
|
1485
1556
|
|
|
1557
|
+
/**
|
|
1558
|
+
* @notice Gets the unique identifier string for this EVVM instance
|
|
1559
|
+
* @dev Returns the EvvmID used for distinguishing different EVVM deployments
|
|
1560
|
+
* @return Unique EvvmID string
|
|
1561
|
+
*/
|
|
1562
|
+
function getEvvmID() external view returns (uint256) {
|
|
1563
|
+
return core.getEvvmID();
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1486
1566
|
/**
|
|
1487
1567
|
* @notice Gets the current EVVM contract address
|
|
1488
1568
|
* @dev Returns the address of the EVVM contract used for payment processing
|
|
1489
1569
|
* @return The current EVVM contract address
|
|
1490
1570
|
*/
|
|
1491
|
-
function
|
|
1492
|
-
return
|
|
1571
|
+
function getCoreAddress() public view returns (address) {
|
|
1572
|
+
return coreAddress.current;
|
|
1493
1573
|
}
|
|
1494
1574
|
|
|
1495
1575
|
/**
|
|
@@ -1499,7 +1579,7 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1499
1579
|
* @return proposalEvvmAddress Proposed new EVVM address (if any)
|
|
1500
1580
|
* @return timeToAcceptEvvmAddress Timestamp when proposal can be accepted
|
|
1501
1581
|
*/
|
|
1502
|
-
function
|
|
1582
|
+
function getCoreAddressFullDetails()
|
|
1503
1583
|
public
|
|
1504
1584
|
view
|
|
1505
1585
|
returns (
|
|
@@ -1509,9 +1589,9 @@ contract NameService is AsyncNonce, NameServiceStructs {
|
|
|
1509
1589
|
)
|
|
1510
1590
|
{
|
|
1511
1591
|
return (
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1592
|
+
coreAddress.current,
|
|
1593
|
+
coreAddress.proposal,
|
|
1594
|
+
coreAddress.timeToAccept
|
|
1515
1595
|
);
|
|
1516
1596
|
}
|
|
1517
1597
|
}
|