@theqrl/qrl-contracts 0.1.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/interfaces/ISQRCTN1.hyp +6 -0
- package/interfaces/IZRC165.hyp +6 -0
- package/interfaces/IZRC4906.hyp +20 -0
- package/interfaces/draft-IZRC6093.hyp +161 -0
- package/package.json +26 -0
- package/token/SQRCTB1/ISQRCTB1.hyp +123 -0
- package/token/SQRCTB1/ISQRCTB1Receiver.hyp +59 -0
- package/token/SQRCTB1/SQRCTB1.hyp +389 -0
- package/token/SQRCTB1/extensions/ISQRCTB1MetadataURI.hyp +20 -0
- package/token/SQRCTB1/utils/SQRCTB1Utils.hyp +88 -0
- package/token/SQRCTF1/ISQRCTF1.hyp +79 -0
- package/token/SQRCTF1/SQRCTF1.hyp +305 -0
- package/token/SQRCTF1/extensions/ISQRCTF1Metadata.hyp +26 -0
- package/token/SQRCTN1/ISQRCTN1.hyp +135 -0
- package/token/SQRCTN1/ISQRCTN1Receiver.hyp +28 -0
- package/token/SQRCTN1/SQRCTN1.hyp +430 -0
- package/token/SQRCTN1/extensions/ISQRCTN1Metadata.hyp +27 -0
- package/token/SQRCTN1/extensions/SQRCTN1URIStorage.hyp +58 -0
- package/token/SQRCTN1/utils/SQRCTN1Utils.hyp +50 -0
- package/utils/Arrays.hyp +552 -0
- package/utils/Comparators.hyp +19 -0
- package/utils/Context.hyp +28 -0
- package/utils/Counters.hyp +43 -0
- package/utils/Panic.hyp +57 -0
- package/utils/SlotDerivation.hyp +155 -0
- package/utils/StorageSlot.hyp +143 -0
- package/utils/Strings.hyp +490 -0
- package/utils/introspection/IZRC165.hyp +25 -0
- package/utils/introspection/ZRC165.hyp +25 -0
- package/utils/math/Math.hyp +749 -0
- package/utils/math/SafeCast.hyp +1162 -0
- package/utils/math/SignedMath.hyp +68 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// QRL Contracts (last updated v0.1.0) (token/SQRCTB1/SQRCTB1.hyp)
|
|
3
|
+
|
|
4
|
+
pragma hyperion >=0.0;
|
|
5
|
+
|
|
6
|
+
import {ISQRCTB1} from "./ISQRCTB1.hyp";
|
|
7
|
+
import {ISQRCTB1MetadataURI} from "./extensions/ISQRCTB1MetadataURI.hyp";
|
|
8
|
+
import {SQRCTB1Utils} from "./utils/SQRCTB1Utils.hyp";
|
|
9
|
+
import {Context} from "../../utils/Context.hyp";
|
|
10
|
+
import {IZRC165, ZRC165} from "../../utils/introspection/ZRC165.hyp";
|
|
11
|
+
import {Arrays} from "../../utils/Arrays.hyp";
|
|
12
|
+
import {ISQRCTB1Errors} from "../../interfaces/draft-IZRC6093.hyp";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @dev Implementation of the basic standard multi-token.
|
|
16
|
+
* See https://eips.ethereum.org/EIPS/eip-1155
|
|
17
|
+
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
|
|
18
|
+
*/
|
|
19
|
+
abstract contract SQRCTB1 is Context, ZRC165, ISQRCTB1, ISQRCTB1MetadataURI, ISQRCTB1Errors {
|
|
20
|
+
using Arrays for uint256[];
|
|
21
|
+
using Arrays for address[];
|
|
22
|
+
|
|
23
|
+
mapping(uint256 id => mapping(address account => uint256)) private _balances;
|
|
24
|
+
|
|
25
|
+
mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
|
|
26
|
+
|
|
27
|
+
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
|
|
28
|
+
string private _uri;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @dev See {_setURI}.
|
|
32
|
+
*/
|
|
33
|
+
constructor(string memory uri_) {
|
|
34
|
+
_setURI(uri_);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// @inheritdoc IZRC165
|
|
38
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override(ZRC165, IZRC165) returns (bool) {
|
|
39
|
+
return
|
|
40
|
+
interfaceId == type(ISQRCTB1).interfaceId ||
|
|
41
|
+
interfaceId == type(ISQRCTB1MetadataURI).interfaceId ||
|
|
42
|
+
super.supportsInterface(interfaceId);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @dev See {ISQRCTB1MetadataURI-uri}.
|
|
47
|
+
*
|
|
48
|
+
* This implementation returns the same URI for *all* token types. It relies
|
|
49
|
+
* on the token type ID substitution mechanism
|
|
50
|
+
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ZRC].
|
|
51
|
+
*
|
|
52
|
+
* Clients calling this function must replace the `\{id\}` substring with the
|
|
53
|
+
* actual token type ID.
|
|
54
|
+
*/
|
|
55
|
+
function uri(uint256 /* id */) public view virtual returns (string memory) {
|
|
56
|
+
return _uri;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// @inheritdoc ISQRCTB1
|
|
60
|
+
function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
|
|
61
|
+
return _balances[id][account];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @dev See {ISQRCTB1-balanceOfBatch}.
|
|
66
|
+
*
|
|
67
|
+
* Requirements:
|
|
68
|
+
*
|
|
69
|
+
* - `accounts` and `ids` must have the same length.
|
|
70
|
+
*/
|
|
71
|
+
function balanceOfBatch(
|
|
72
|
+
address[] memory accounts,
|
|
73
|
+
uint256[] memory ids
|
|
74
|
+
) public view virtual returns (uint256[] memory) {
|
|
75
|
+
if (accounts.length != ids.length) {
|
|
76
|
+
revert SQRCTB1InvalidArrayLength(ids.length, accounts.length);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
uint256[] memory batchBalances = new uint256[](accounts.length);
|
|
80
|
+
|
|
81
|
+
for (uint256 i = 0; i < accounts.length; ++i) {
|
|
82
|
+
batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return batchBalances;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// @inheritdoc ISQRCTB1
|
|
89
|
+
function setApprovalForAll(address operator, bool approved) public virtual {
|
|
90
|
+
_setApprovalForAll(_msgSender(), operator, approved);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// @inheritdoc ISQRCTB1
|
|
94
|
+
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
|
|
95
|
+
return _operatorApprovals[account][operator];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// @inheritdoc ISQRCTB1
|
|
99
|
+
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
|
|
100
|
+
address sender = _msgSender();
|
|
101
|
+
if (from != sender && !isApprovedForAll(from, sender)) {
|
|
102
|
+
revert SQRCTB1MissingApprovalForAll(sender, from);
|
|
103
|
+
}
|
|
104
|
+
_safeTransferFrom(from, to, id, value, data);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// @inheritdoc ISQRCTB1
|
|
108
|
+
function safeBatchTransferFrom(
|
|
109
|
+
address from,
|
|
110
|
+
address to,
|
|
111
|
+
uint256[] memory ids,
|
|
112
|
+
uint256[] memory values,
|
|
113
|
+
bytes memory data
|
|
114
|
+
) public virtual {
|
|
115
|
+
address sender = _msgSender();
|
|
116
|
+
if (from != sender && !isApprovedForAll(from, sender)) {
|
|
117
|
+
revert SQRCTB1MissingApprovalForAll(sender, from);
|
|
118
|
+
}
|
|
119
|
+
_safeBatchTransferFrom(from, to, ids, values, data);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from`
|
|
124
|
+
* (or `to`) is the zero address.
|
|
125
|
+
*
|
|
126
|
+
* Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.
|
|
127
|
+
*
|
|
128
|
+
* Requirements:
|
|
129
|
+
*
|
|
130
|
+
* - If `to` refers to a smart contract, it must implement either {ISQRCTB1Receiver-onSQRCTB1Received}
|
|
131
|
+
* or {ISQRCTB1Receiver-onSQRCTB1BatchReceived} and return the acceptance magic value.
|
|
132
|
+
* - `ids` and `values` must have the same length.
|
|
133
|
+
*
|
|
134
|
+
* NOTE: The SQRC-TB1 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead.
|
|
135
|
+
*/
|
|
136
|
+
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
|
|
137
|
+
if (ids.length != values.length) {
|
|
138
|
+
revert SQRCTB1InvalidArrayLength(ids.length, values.length);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
address operator = _msgSender();
|
|
142
|
+
|
|
143
|
+
for (uint256 i = 0; i < ids.length; ++i) {
|
|
144
|
+
uint256 id = ids.unsafeMemoryAccess(i);
|
|
145
|
+
uint256 value = values.unsafeMemoryAccess(i);
|
|
146
|
+
|
|
147
|
+
if (from != address(0)) {
|
|
148
|
+
uint256 fromBalance = _balances[id][from];
|
|
149
|
+
if (fromBalance < value) {
|
|
150
|
+
revert SQRCTB1InsufficientBalance(from, fromBalance, value, id);
|
|
151
|
+
}
|
|
152
|
+
unchecked {
|
|
153
|
+
// Overflow not possible: value <= fromBalance
|
|
154
|
+
_balances[id][from] = fromBalance - value;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (to != address(0)) {
|
|
159
|
+
_balances[id][to] += value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (ids.length == 1) {
|
|
164
|
+
uint256 id = ids.unsafeMemoryAccess(0);
|
|
165
|
+
uint256 value = values.unsafeMemoryAccess(0);
|
|
166
|
+
emit TransferSingle(operator, from, to, id, value);
|
|
167
|
+
} else {
|
|
168
|
+
emit TransferBatch(operator, from, to, ids, values);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @dev Version of {_update} that performs the token acceptance check by calling
|
|
174
|
+
* {ISQRCTB1Receiver-onSQRCTB1Received} or {ISQRCTB1Receiver-onSQRCTB1BatchReceived} on the receiver address if it
|
|
175
|
+
* contains code (eg. is a smart contract at the moment of execution).
|
|
176
|
+
*
|
|
177
|
+
* IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any
|
|
178
|
+
* update to the contract state after this function would break the check-effect-interaction pattern. Consider
|
|
179
|
+
* overriding {_update} instead.
|
|
180
|
+
*/
|
|
181
|
+
function _updateWithAcceptanceCheck(
|
|
182
|
+
address from,
|
|
183
|
+
address to,
|
|
184
|
+
uint256[] memory ids,
|
|
185
|
+
uint256[] memory values,
|
|
186
|
+
bytes memory data
|
|
187
|
+
) internal virtual {
|
|
188
|
+
_update(from, to, ids, values);
|
|
189
|
+
if (to != address(0)) {
|
|
190
|
+
address operator = _msgSender();
|
|
191
|
+
if (ids.length == 1) {
|
|
192
|
+
uint256 id = ids.unsafeMemoryAccess(0);
|
|
193
|
+
uint256 value = values.unsafeMemoryAccess(0);
|
|
194
|
+
SQRCTB1Utils.checkOnSQRCTB1Received(operator, from, to, id, value, data);
|
|
195
|
+
} else {
|
|
196
|
+
SQRCTB1Utils.checkOnSQRCTB1BatchReceived(operator, from, to, ids, values, data);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @dev Transfers a `value` tokens of token type `id` from `from` to `to`.
|
|
203
|
+
*
|
|
204
|
+
* Emits a {TransferSingle} event.
|
|
205
|
+
*
|
|
206
|
+
* Requirements:
|
|
207
|
+
*
|
|
208
|
+
* - `to` cannot be the zero address.
|
|
209
|
+
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
|
|
210
|
+
* - If `to` refers to a smart contract, it must implement {ISQRCTB1Receiver-onSQRCTB1Received} and return the
|
|
211
|
+
* acceptance magic value.
|
|
212
|
+
*/
|
|
213
|
+
function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
|
|
214
|
+
if (to == address(0)) {
|
|
215
|
+
revert SQRCTB1InvalidReceiver(address(0));
|
|
216
|
+
}
|
|
217
|
+
if (from == address(0)) {
|
|
218
|
+
revert SQRCTB1InvalidSender(address(0));
|
|
219
|
+
}
|
|
220
|
+
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
|
|
221
|
+
_updateWithAcceptanceCheck(from, to, ids, values, data);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @dev xref:ROOT:zrc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
|
|
226
|
+
*
|
|
227
|
+
* Emits a {TransferBatch} event.
|
|
228
|
+
*
|
|
229
|
+
* Requirements:
|
|
230
|
+
*
|
|
231
|
+
* - If `to` refers to a smart contract, it must implement {ISQRCTB1Receiver-onSQRCTB1BatchReceived} and return the
|
|
232
|
+
* acceptance magic value.
|
|
233
|
+
* - `ids` and `values` must have the same length.
|
|
234
|
+
*/
|
|
235
|
+
function _safeBatchTransferFrom(
|
|
236
|
+
address from,
|
|
237
|
+
address to,
|
|
238
|
+
uint256[] memory ids,
|
|
239
|
+
uint256[] memory values,
|
|
240
|
+
bytes memory data
|
|
241
|
+
) internal {
|
|
242
|
+
if (to == address(0)) {
|
|
243
|
+
revert SQRCTB1InvalidReceiver(address(0));
|
|
244
|
+
}
|
|
245
|
+
if (from == address(0)) {
|
|
246
|
+
revert SQRCTB1InvalidSender(address(0));
|
|
247
|
+
}
|
|
248
|
+
_updateWithAcceptanceCheck(from, to, ids, values, data);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @dev Sets a new URI for all token types, by relying on the token type ID
|
|
253
|
+
* substitution mechanism
|
|
254
|
+
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ZRC].
|
|
255
|
+
*
|
|
256
|
+
* By this mechanism, any occurrence of the `\{id\}` substring in either the
|
|
257
|
+
* URI or any of the values in the JSON file at said URI will be replaced by
|
|
258
|
+
* clients with the token type ID.
|
|
259
|
+
*
|
|
260
|
+
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
|
|
261
|
+
* interpreted by clients as
|
|
262
|
+
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
|
|
263
|
+
* for token type ID 0x4cce0.
|
|
264
|
+
*
|
|
265
|
+
* See {uri}.
|
|
266
|
+
*
|
|
267
|
+
* Because these URIs cannot be meaningfully represented by the {URI} event,
|
|
268
|
+
* this function emits no events.
|
|
269
|
+
*/
|
|
270
|
+
function _setURI(string memory newuri) internal virtual {
|
|
271
|
+
_uri = newuri;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`.
|
|
276
|
+
*
|
|
277
|
+
* Emits a {TransferSingle} event.
|
|
278
|
+
*
|
|
279
|
+
* Requirements:
|
|
280
|
+
*
|
|
281
|
+
* - `to` cannot be the zero address.
|
|
282
|
+
* - If `to` refers to a smart contract, it must implement {ISQRCTB1Receiver-onSQRCTB1Received} and return the
|
|
283
|
+
* acceptance magic value.
|
|
284
|
+
*/
|
|
285
|
+
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
|
|
286
|
+
if (to == address(0)) {
|
|
287
|
+
revert SQRCTB1InvalidReceiver(address(0));
|
|
288
|
+
}
|
|
289
|
+
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
|
|
290
|
+
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @dev xref:ROOT:zrc1155.adoc#batch-operations[Batched] version of {_mint}.
|
|
295
|
+
*
|
|
296
|
+
* Emits a {TransferBatch} event.
|
|
297
|
+
*
|
|
298
|
+
* Requirements:
|
|
299
|
+
*
|
|
300
|
+
* - `ids` and `values` must have the same length.
|
|
301
|
+
* - `to` cannot be the zero address.
|
|
302
|
+
* - If `to` refers to a smart contract, it must implement {ISQRCTB1Receiver-onSQRCTB1BatchReceived} and return the
|
|
303
|
+
* acceptance magic value.
|
|
304
|
+
*/
|
|
305
|
+
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
|
|
306
|
+
if (to == address(0)) {
|
|
307
|
+
revert SQRCTB1InvalidReceiver(address(0));
|
|
308
|
+
}
|
|
309
|
+
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @dev Destroys a `value` amount of tokens of type `id` from `from`
|
|
314
|
+
*
|
|
315
|
+
* Emits a {TransferSingle} event.
|
|
316
|
+
*
|
|
317
|
+
* Requirements:
|
|
318
|
+
*
|
|
319
|
+
* - `from` cannot be the zero address.
|
|
320
|
+
* - `from` must have at least `value` amount of tokens of type `id`.
|
|
321
|
+
*/
|
|
322
|
+
function _burn(address from, uint256 id, uint256 value) internal {
|
|
323
|
+
if (from == address(0)) {
|
|
324
|
+
revert SQRCTB1InvalidSender(address(0));
|
|
325
|
+
}
|
|
326
|
+
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
|
|
327
|
+
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @dev xref:ROOT:zrc1155.adoc#batch-operations[Batched] version of {_burn}.
|
|
332
|
+
*
|
|
333
|
+
* Emits a {TransferBatch} event.
|
|
334
|
+
*
|
|
335
|
+
* Requirements:
|
|
336
|
+
*
|
|
337
|
+
* - `from` cannot be the zero address.
|
|
338
|
+
* - `from` must have at least `value` amount of tokens of type `id`.
|
|
339
|
+
* - `ids` and `values` must have the same length.
|
|
340
|
+
*/
|
|
341
|
+
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
|
|
342
|
+
if (from == address(0)) {
|
|
343
|
+
revert SQRCTB1InvalidSender(address(0));
|
|
344
|
+
}
|
|
345
|
+
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* @dev Approve `operator` to operate on all of `owner` tokens
|
|
350
|
+
*
|
|
351
|
+
* Emits an {ApprovalForAll} event.
|
|
352
|
+
*
|
|
353
|
+
* Requirements:
|
|
354
|
+
*
|
|
355
|
+
* - `operator` cannot be the zero address.
|
|
356
|
+
*/
|
|
357
|
+
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
|
|
358
|
+
if (operator == address(0)) {
|
|
359
|
+
revert SQRCTB1InvalidOperator(address(0));
|
|
360
|
+
}
|
|
361
|
+
_operatorApprovals[owner][operator] = approved;
|
|
362
|
+
emit ApprovalForAll(owner, operator, approved);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @dev Creates an array in memory with only one value for each of the elements provided.
|
|
367
|
+
*/
|
|
368
|
+
function _asSingletonArrays(
|
|
369
|
+
uint256 element1,
|
|
370
|
+
uint256 element2
|
|
371
|
+
) private pure returns (uint256[] memory array1, uint256[] memory array2) {
|
|
372
|
+
assembly ("memory-safe") {
|
|
373
|
+
// Load the free memory pointer
|
|
374
|
+
array1 := mload(0x40)
|
|
375
|
+
// Set array length to 1
|
|
376
|
+
mstore(array1, 1)
|
|
377
|
+
// Store the single element at the next word after the length (where content starts)
|
|
378
|
+
mstore(add(array1, 0x20), element1)
|
|
379
|
+
|
|
380
|
+
// Repeat for next array locating it right after the first array
|
|
381
|
+
array2 := add(array1, 0x40)
|
|
382
|
+
mstore(array2, 1)
|
|
383
|
+
mstore(add(array2, 0x20), element2)
|
|
384
|
+
|
|
385
|
+
// Update the free memory pointer by pointing after the second array
|
|
386
|
+
mstore(0x40, add(array2, 0x40))
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// QRL Contracts (last updated v0.1.0) (token/SQRCTB1/extensions/ISQRCTB1MetadataURI.hyp)
|
|
3
|
+
|
|
4
|
+
pragma hyperion >=0.0;
|
|
5
|
+
|
|
6
|
+
import {ISQRCTB1} from "../ISQRCTB1.hyp";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @dev Interface of the optional SQRCTB1MetadataExtension interface, as defined
|
|
10
|
+
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ZRC].
|
|
11
|
+
*/
|
|
12
|
+
interface ISQRCTB1MetadataURI is ISQRCTB1 {
|
|
13
|
+
/**
|
|
14
|
+
* @dev Returns the URI for token type `id`.
|
|
15
|
+
*
|
|
16
|
+
* If the `\{id\}` substring is present in the URI, it must be replaced by
|
|
17
|
+
* clients with the actual token type ID.
|
|
18
|
+
*/
|
|
19
|
+
function uri(uint256 id) external view returns (string memory);
|
|
20
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// QRL Contracts (last updated v0.1.0) (token/SQRCTB1/utils/SQRCTB1Utils.hyp)
|
|
3
|
+
|
|
4
|
+
pragma hyperion >=0.0;
|
|
5
|
+
|
|
6
|
+
import {ISQRCTB1Receiver} from "../ISQRCTB1Receiver.hyp";
|
|
7
|
+
import {ISQRCTB1Errors} from "../../../interfaces/draft-IZRC6093.hyp";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @dev Library that provide common SQRC-TB1 utility functions.
|
|
11
|
+
*
|
|
12
|
+
* See https://eips.ethereum.org/EIPS/eip-1155[SQRC-TB1].
|
|
13
|
+
*
|
|
14
|
+
* _Available since v5.1._
|
|
15
|
+
*/
|
|
16
|
+
library SQRCTB1Utils {
|
|
17
|
+
/**
|
|
18
|
+
* @dev Performs an acceptance check for the provided `operator` by calling {ISQRCTB1Receiver-onSQRCTB1Received}
|
|
19
|
+
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
|
|
20
|
+
*
|
|
21
|
+
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
|
|
22
|
+
* Otherwise, the recipient must implement {ISQRCTB1Receiver-onSQRCTB1Received} and return the acceptance magic value to accept
|
|
23
|
+
* the transfer.
|
|
24
|
+
*/
|
|
25
|
+
function checkOnSQRCTB1Received(
|
|
26
|
+
address operator,
|
|
27
|
+
address from,
|
|
28
|
+
address to,
|
|
29
|
+
uint256 id,
|
|
30
|
+
uint256 value,
|
|
31
|
+
bytes memory data
|
|
32
|
+
) internal {
|
|
33
|
+
if (to.code.length > 0) {
|
|
34
|
+
try ISQRCTB1Receiver(to).onSQRCTB1Received(operator, from, id, value, data) returns (bytes4 response) {
|
|
35
|
+
if (response != ISQRCTB1Receiver.onSQRCTB1Received.selector) {
|
|
36
|
+
// Tokens rejected
|
|
37
|
+
revert ISQRCTB1Errors.SQRCTB1InvalidReceiver(to);
|
|
38
|
+
}
|
|
39
|
+
} catch (bytes memory reason) {
|
|
40
|
+
if (reason.length == 0) {
|
|
41
|
+
// non-ISQRCTB1Receiver implementer
|
|
42
|
+
revert ISQRCTB1Errors.SQRCTB1InvalidReceiver(to);
|
|
43
|
+
} else {
|
|
44
|
+
assembly ("memory-safe") {
|
|
45
|
+
revert(add(32, reason), mload(reason))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @dev Performs a batch acceptance check for the provided `operator` by calling {ISQRCTB1Receiver-onSQRCTB1BatchReceived}
|
|
54
|
+
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
|
|
55
|
+
*
|
|
56
|
+
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
|
|
57
|
+
* Otherwise, the recipient must implement {ISQRCTB1Receiver-onSQRCTB1Received} and return the acceptance magic value to accept
|
|
58
|
+
* the transfer.
|
|
59
|
+
*/
|
|
60
|
+
function checkOnSQRCTB1BatchReceived(
|
|
61
|
+
address operator,
|
|
62
|
+
address from,
|
|
63
|
+
address to,
|
|
64
|
+
uint256[] memory ids,
|
|
65
|
+
uint256[] memory values,
|
|
66
|
+
bytes memory data
|
|
67
|
+
) internal {
|
|
68
|
+
if (to.code.length > 0) {
|
|
69
|
+
try ISQRCTB1Receiver(to).onSQRCTB1BatchReceived(operator, from, ids, values, data) returns (
|
|
70
|
+
bytes4 response
|
|
71
|
+
) {
|
|
72
|
+
if (response != ISQRCTB1Receiver.onSQRCTB1BatchReceived.selector) {
|
|
73
|
+
// Tokens rejected
|
|
74
|
+
revert ISQRCTB1Errors.SQRCTB1InvalidReceiver(to);
|
|
75
|
+
}
|
|
76
|
+
} catch (bytes memory reason) {
|
|
77
|
+
if (reason.length == 0) {
|
|
78
|
+
// non-ISQRCTB1Receiver implementer
|
|
79
|
+
revert ISQRCTB1Errors.SQRCTB1InvalidReceiver(to);
|
|
80
|
+
} else {
|
|
81
|
+
assembly ("memory-safe") {
|
|
82
|
+
revert(add(32, reason), mload(reason))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// QRL Contracts (last updated v0.1.0) (token/SQRCTF1/ISQRCTF1.hyp)
|
|
3
|
+
|
|
4
|
+
pragma hyperion >=0.0;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @dev Interface of the SQRC-TF1 standard as defined in the ZRC.
|
|
8
|
+
*/
|
|
9
|
+
interface ISQRCTF1 {
|
|
10
|
+
/**
|
|
11
|
+
* @dev Emitted when `value` tokens are moved from one account (`from`) to
|
|
12
|
+
* another (`to`).
|
|
13
|
+
*
|
|
14
|
+
* Note that `value` may be zero.
|
|
15
|
+
*/
|
|
16
|
+
event Transfer(address indexed from, address indexed to, uint256 value);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
|
|
20
|
+
* a call to {approve}. `value` is the new allowance.
|
|
21
|
+
*/
|
|
22
|
+
event Approval(address indexed owner, address indexed spender, uint256 value);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @dev Returns the value of tokens in existence.
|
|
26
|
+
*/
|
|
27
|
+
function totalSupply() external view returns (uint256);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @dev Returns the value of tokens owned by `account`.
|
|
31
|
+
*/
|
|
32
|
+
function balanceOf(address account) external view returns (uint256);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
|
|
36
|
+
*
|
|
37
|
+
* Returns a boolean value indicating whether the operation succeeded.
|
|
38
|
+
*
|
|
39
|
+
* Emits a {Transfer} event.
|
|
40
|
+
*/
|
|
41
|
+
function transfer(address to, uint256 value) external returns (bool);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @dev Returns the remaining number of tokens that `spender` will be
|
|
45
|
+
* allowed to spend on behalf of `owner` through {transferFrom}. This is
|
|
46
|
+
* zero by default.
|
|
47
|
+
*
|
|
48
|
+
* This value changes when {approve} or {transferFrom} are called.
|
|
49
|
+
*/
|
|
50
|
+
function allowance(address owner, address spender) external view returns (uint256);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
|
|
54
|
+
* caller's tokens.
|
|
55
|
+
*
|
|
56
|
+
* Returns a boolean value indicating whether the operation succeeded.
|
|
57
|
+
*
|
|
58
|
+
* IMPORTANT: Beware that changing an allowance with this method brings the risk
|
|
59
|
+
* that someone may use both the old and the new allowance by unfortunate
|
|
60
|
+
* transaction ordering. One possible solution to mitigate this race
|
|
61
|
+
* condition is to first reduce the spender's allowance to 0 and set the
|
|
62
|
+
* desired value afterwards:
|
|
63
|
+
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
|
64
|
+
*
|
|
65
|
+
* Emits an {Approval} event.
|
|
66
|
+
*/
|
|
67
|
+
function approve(address spender, uint256 value) external returns (bool);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @dev Moves a `value` amount of tokens from `from` to `to` using the
|
|
71
|
+
* allowance mechanism. `value` is then deducted from the caller's
|
|
72
|
+
* allowance.
|
|
73
|
+
*
|
|
74
|
+
* Returns a boolean value indicating whether the operation succeeded.
|
|
75
|
+
*
|
|
76
|
+
* Emits a {Transfer} event.
|
|
77
|
+
*/
|
|
78
|
+
function transferFrom(address from, address to, uint256 value) external returns (bool);
|
|
79
|
+
}
|