@lukso/lsp8-contracts 0.17.3 → 0.18.1

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.
Files changed (42) hide show
  1. package/README.md +69 -24
  2. package/artifacts/IAccessControlExtended.json +1 -1
  3. package/artifacts/ILSP8CappedBalance.json +1 -1
  4. package/artifacts/ILSP8CappedSupply.json +1 -1
  5. package/artifacts/ILSP8IdentifiableDigitalAsset.json +1 -1
  6. package/artifacts/ILSP8Mintable.json +1 -1
  7. package/artifacts/ILSP8NonTransferable.json +8 -2
  8. package/artifacts/ILSP8Revokable.json +38 -1
  9. package/artifacts/LSP8Burnable.json +1 -1
  10. package/artifacts/LSP8BurnableInitAbstract.json +1 -1
  11. package/artifacts/LSP8CappedBalanceAbstract.json +1 -1
  12. package/artifacts/LSP8CappedBalanceInitAbstract.json +1 -1
  13. package/artifacts/LSP8CappedSupplyAbstract.json +1 -1
  14. package/artifacts/LSP8CappedSupplyInitAbstract.json +1 -1
  15. package/artifacts/LSP8CustomizableToken.json +64 -21
  16. package/artifacts/LSP8CustomizableTokenInit.json +59 -16
  17. package/artifacts/LSP8Enumerable.json +1 -1
  18. package/artifacts/LSP8EnumerableInitAbstract.json +1 -1
  19. package/artifacts/LSP8IdentifiableDigitalAsset.json +1 -1
  20. package/artifacts/LSP8IdentifiableDigitalAssetInitAbstract.json +1 -1
  21. package/artifacts/LSP8Mintable.json +1 -1
  22. package/artifacts/LSP8MintableAbstract.json +1 -1
  23. package/artifacts/LSP8MintableInit.json +1 -1
  24. package/artifacts/LSP8MintableInitAbstract.json +1 -1
  25. package/artifacts/LSP8NonTransferableAbstract.json +20 -14
  26. package/artifacts/LSP8NonTransferableInitAbstract.json +20 -14
  27. package/artifacts/LSP8RevokableAbstract.json +38 -1
  28. package/artifacts/LSP8RevokableInitAbstract.json +38 -1
  29. package/artifacts/LSP8Votes.json +1 -1
  30. package/artifacts/LSP8VotesInitAbstract.json +1 -1
  31. package/contracts/extensions/LSP8NonTransferable/ILSP8NonTransferable.sol +9 -3
  32. package/contracts/extensions/LSP8NonTransferable/LSP8NonTransferableAbstract.sol +17 -8
  33. package/contracts/extensions/LSP8NonTransferable/LSP8NonTransferableInitAbstract.sol +17 -8
  34. package/contracts/extensions/LSP8Revokable/ILSP8Revokable.sol +9 -0
  35. package/contracts/extensions/LSP8Revokable/LSP8RevokableAbstract.sol +8 -0
  36. package/contracts/extensions/LSP8Revokable/LSP8RevokableInitAbstract.sol +15 -1
  37. package/dist/abi.cjs +169 -29
  38. package/dist/abi.d.cts +216 -41
  39. package/dist/abi.d.mts +216 -41
  40. package/dist/abi.d.ts +216 -41
  41. package/dist/abi.mjs +169 -29
  42. package/package.json +1 -1
@@ -564,6 +564,12 @@
564
564
  {
565
565
  "anonymous": false,
566
566
  "inputs": [
567
+ {
568
+ "indexed": true,
569
+ "internalType": "bool",
570
+ "name": "nonTransferabilityEnabled",
571
+ "type": "bool"
572
+ },
567
573
  {
568
574
  "indexed": true,
569
575
  "internalType": "uint256",
@@ -943,6 +949,19 @@
943
949
  "stateMutability": "nonpayable",
944
950
  "type": "function"
945
951
  },
952
+ {
953
+ "inputs": [],
954
+ "name": "nonTransferabilityEnabled",
955
+ "outputs": [
956
+ {
957
+ "internalType": "bool",
958
+ "name": "",
959
+ "type": "bool"
960
+ }
961
+ ],
962
+ "stateMutability": "view",
963
+ "type": "function"
964
+ },
946
965
  {
947
966
  "inputs": [],
948
967
  "name": "owner",
@@ -1282,19 +1301,6 @@
1282
1301
  "stateMutability": "nonpayable",
1283
1302
  "type": "function"
1284
1303
  },
1285
- {
1286
- "inputs": [],
1287
- "name": "transferLockEnabled",
1288
- "outputs": [
1289
- {
1290
- "internalType": "bool",
1291
- "name": "",
1292
- "type": "bool"
1293
- }
1294
- ],
1295
- "stateMutability": "view",
1296
- "type": "function"
1297
- },
1298
1304
  {
1299
1305
  "inputs": [],
1300
1306
  "name": "transferLockEnd",
@@ -1363,5 +1369,5 @@
1363
1369
  "deployedLinkReferences": {},
1364
1370
  "immutableReferences": {},
1365
1371
  "inputSourceName": "project/contracts/extensions/LSP8NonTransferable/LSP8NonTransferableAbstract.sol",
1366
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1372
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1367
1373
  }
@@ -572,6 +572,12 @@
572
572
  {
573
573
  "anonymous": false,
574
574
  "inputs": [
575
+ {
576
+ "indexed": true,
577
+ "internalType": "bool",
578
+ "name": "nonTransferabilityEnabled",
579
+ "type": "bool"
580
+ },
575
581
  {
576
582
  "indexed": true,
577
583
  "internalType": "uint256",
@@ -951,6 +957,19 @@
951
957
  "stateMutability": "nonpayable",
952
958
  "type": "function"
953
959
  },
960
+ {
961
+ "inputs": [],
962
+ "name": "nonTransferabilityEnabled",
963
+ "outputs": [
964
+ {
965
+ "internalType": "bool",
966
+ "name": "",
967
+ "type": "bool"
968
+ }
969
+ ],
970
+ "stateMutability": "view",
971
+ "type": "function"
972
+ },
954
973
  {
955
974
  "inputs": [],
956
975
  "name": "owner",
@@ -1290,19 +1309,6 @@
1290
1309
  "stateMutability": "nonpayable",
1291
1310
  "type": "function"
1292
1311
  },
1293
- {
1294
- "inputs": [],
1295
- "name": "transferLockEnabled",
1296
- "outputs": [
1297
- {
1298
- "internalType": "bool",
1299
- "name": "",
1300
- "type": "bool"
1301
- }
1302
- ],
1303
- "stateMutability": "view",
1304
- "type": "function"
1305
- },
1306
1312
  {
1307
1313
  "inputs": [],
1308
1314
  "name": "transferLockEnd",
@@ -1371,5 +1377,5 @@
1371
1377
  "deployedLinkReferences": {},
1372
1378
  "immutableReferences": {},
1373
1379
  "inputSourceName": "project/contracts/extensions/LSP8NonTransferable/LSP8NonTransferableInitAbstract.sol",
1374
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1380
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1375
1381
  }
@@ -516,6 +516,43 @@
516
516
  "name": "TokenIdDataChanged",
517
517
  "type": "event"
518
518
  },
519
+ {
520
+ "anonymous": false,
521
+ "inputs": [
522
+ {
523
+ "indexed": true,
524
+ "internalType": "address",
525
+ "name": "revoker",
526
+ "type": "address"
527
+ },
528
+ {
529
+ "indexed": true,
530
+ "internalType": "address",
531
+ "name": "from",
532
+ "type": "address"
533
+ },
534
+ {
535
+ "indexed": true,
536
+ "internalType": "address",
537
+ "name": "to",
538
+ "type": "address"
539
+ },
540
+ {
541
+ "indexed": false,
542
+ "internalType": "bytes32",
543
+ "name": "tokenId",
544
+ "type": "bytes32"
545
+ },
546
+ {
547
+ "indexed": false,
548
+ "internalType": "bytes",
549
+ "name": "data",
550
+ "type": "bytes"
551
+ }
552
+ ],
553
+ "name": "TokenRevoked",
554
+ "type": "event"
555
+ },
519
556
  {
520
557
  "anonymous": false,
521
558
  "inputs": [
@@ -1313,5 +1350,5 @@
1313
1350
  "deployedLinkReferences": {},
1314
1351
  "immutableReferences": {},
1315
1352
  "inputSourceName": "project/contracts/extensions/LSP8Revokable/LSP8RevokableAbstract.sol",
1316
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1353
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1317
1354
  }
@@ -524,6 +524,43 @@
524
524
  "name": "TokenIdDataChanged",
525
525
  "type": "event"
526
526
  },
527
+ {
528
+ "anonymous": false,
529
+ "inputs": [
530
+ {
531
+ "indexed": true,
532
+ "internalType": "address",
533
+ "name": "revoker",
534
+ "type": "address"
535
+ },
536
+ {
537
+ "indexed": true,
538
+ "internalType": "address",
539
+ "name": "from",
540
+ "type": "address"
541
+ },
542
+ {
543
+ "indexed": true,
544
+ "internalType": "address",
545
+ "name": "to",
546
+ "type": "address"
547
+ },
548
+ {
549
+ "indexed": false,
550
+ "internalType": "bytes32",
551
+ "name": "tokenId",
552
+ "type": "bytes32"
553
+ },
554
+ {
555
+ "indexed": false,
556
+ "internalType": "bytes",
557
+ "name": "data",
558
+ "type": "bytes"
559
+ }
560
+ ],
561
+ "name": "TokenRevoked",
562
+ "type": "event"
563
+ },
527
564
  {
528
565
  "anonymous": false,
529
566
  "inputs": [
@@ -1321,5 +1358,5 @@
1321
1358
  "deployedLinkReferences": {},
1322
1359
  "immutableReferences": {},
1323
1360
  "inputSourceName": "project/contracts/extensions/LSP8Revokable/LSP8RevokableInitAbstract.sol",
1324
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1361
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1325
1362
  }
@@ -1229,5 +1229,5 @@
1229
1229
  "deployedLinkReferences": {},
1230
1230
  "immutableReferences": {},
1231
1231
  "inputSourceName": "project/contracts/extensions/LSP8Votes/LSP8Votes.sol",
1232
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1232
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1233
1233
  }
@@ -1221,5 +1221,5 @@
1221
1221
  "deployedLinkReferences": {},
1222
1222
  "immutableReferences": {},
1223
1223
  "inputSourceName": "project/contracts/extensions/LSP8Votes/LSP8VotesInitAbstract.sol",
1224
- "buildInfoId": "solc-0_8_28-51761251365f530b69e394f3aa78b9f98e3e9d6a"
1224
+ "buildInfoId": "solc-0_8_28-a1f189205db65800e276c245fa7f2fa7071cb3a5"
1225
1225
  }
@@ -5,9 +5,14 @@ pragma solidity ^0.8.27;
5
5
  /// @dev Interface for a non-transferable LSP8 token, enabling control over transferability, lock periods, and role-based exemptions.
6
6
  interface ILSP8NonTransferable {
7
7
  /// @dev Emitted when the transfer lock period is updated.
8
+ /// @param nonTransferabilityEnabled Whether the non-transferability feature is enabled or not.
8
9
  /// @param start The new start timestamp of the transfer lock period.
9
10
  /// @param end The new end timestamp of the transfer lock period.
10
- event TransferLockPeriodChanged(uint256 indexed start, uint256 indexed end);
11
+ event TransferLockPeriodChanged(
12
+ bool indexed nonTransferabilityEnabled,
13
+ uint256 indexed start,
14
+ uint256 indexed end
15
+ );
11
16
 
12
17
  /// @notice The start timestamp of the transfer lock period, at which point the token becomes non-transferable.
13
18
  function transferLockStart() external view returns (uint256);
@@ -17,7 +22,7 @@ interface ILSP8NonTransferable {
17
22
 
18
23
  /// @notice Returns whether the transfer lock feature is still enabled.
19
24
  /// @dev When this returns `false`, the token has been permanently made transferable and the lock period can no longer be updated.
20
- function transferLockEnabled() external view returns (bool);
25
+ function nonTransferabilityEnabled() external view returns (bool);
21
26
 
22
27
  /// @notice Checks if the token is currently transferable.
23
28
  /// @dev Returns true if the token is transferable (based on the lock period). Note that transfers from addresses holding the bypass role and burning (transfers to address(0)) is always allowed, regardless of transferability status.
@@ -34,7 +39,8 @@ interface ILSP8NonTransferable {
34
39
  /// - When `transferLockStart` is set to a value and `transferLockEnd` is 0, it means the tokens becomes non-transferable at a certain point in time and indefinitely (no end time).
35
40
  ///
36
41
  /// - To make the token always non-transferable, set `transferLockStart` to 0 and `transferLockEnd` to type(uint256).max.
37
- /// - To disable completely the non-transferable feature (= make the token always transferable), set both `transferLockStart` and `transferLockEnd` to 0.
42
+ /// - To remove the active lock while keeping the non-transferability feature configurable, set both `newTransferLockStart` and `newTransferLockEnd` to 0. In this state, transfers are currently unrestricted, but the owner can still configure a new lock period later.
43
+ /// - To permanently disable the non-transferability feature and prevent future lock-period updates, use the {makeTransferable} function.
38
44
  ///
39
45
  /// @dev Can only be called by the contract owner. Reverts once {makeTransferable} has been called.
40
46
  ///
@@ -39,7 +39,7 @@ abstract contract LSP8NonTransferableAbstract is
39
39
  uint256 public transferLockEnd;
40
40
 
41
41
  /// @inheritdoc ILSP8NonTransferable
42
- bool public transferLockEnabled;
42
+ bool public nonTransferabilityEnabled;
43
43
 
44
44
  /// @notice Initializes the contract with lock period.
45
45
  /// @param transferLockStart_ The start timestamp of the transfer lock period, 0 to disable.
@@ -51,9 +51,13 @@ abstract contract LSP8NonTransferableAbstract is
51
51
  );
52
52
  transferLockStart = transferLockStart_;
53
53
  transferLockEnd = transferLockEnd_;
54
- transferLockEnabled = true;
54
+ nonTransferabilityEnabled = true;
55
55
 
56
- emit TransferLockPeriodChanged(transferLockStart_, transferLockEnd_);
56
+ emit TransferLockPeriodChanged({
57
+ nonTransferabilityEnabled: true,
58
+ start: transferLockStart_,
59
+ end: transferLockEnd_
60
+ });
57
61
  _grantRole(NON_TRANSFERABLE_BYPASS_ROLE, owner());
58
62
  }
59
63
 
@@ -75,7 +79,7 @@ abstract contract LSP8NonTransferableAbstract is
75
79
  // solhint-disable not-rely-on-time
76
80
  // Transfer-lock windows are inherently time-based; `block.timestamp` is the intended source.
77
81
  function isTransferable() public view virtual override returns (bool) {
78
- if (!transferLockEnabled) return true;
82
+ if (!nonTransferabilityEnabled) return true;
79
83
 
80
84
  bool isTransferLockStartEnabled = transferLockStart != 0;
81
85
  bool isTransferLockEndEnabled = transferLockEnd != 0;
@@ -105,13 +109,17 @@ abstract contract LSP8NonTransferableAbstract is
105
109
  /// @inheritdoc ILSP8NonTransferable
106
110
  /// @custom:info The list of addresses holding the `NON_TRANSFERABLE_BYPASS_ROLE` remains populated after the non-transferable feature is switched off.
107
111
  function makeTransferable() public virtual override onlyOwner {
108
- require(transferLockEnabled, LSP8TokenAlreadyTransferable());
112
+ require(nonTransferabilityEnabled, LSP8TokenAlreadyTransferable());
109
113
 
110
- transferLockEnabled = false;
114
+ nonTransferabilityEnabled = false;
111
115
  transferLockStart = 0;
112
116
  transferLockEnd = 0;
113
117
 
114
- emit TransferLockPeriodChanged({start: 0, end: 0});
118
+ emit TransferLockPeriodChanged({
119
+ nonTransferabilityEnabled: false,
120
+ start: 0,
121
+ end: 0
122
+ });
115
123
  }
116
124
 
117
125
  /// @inheritdoc ILSP8NonTransferable
@@ -119,7 +127,7 @@ abstract contract LSP8NonTransferableAbstract is
119
127
  uint256 newTransferLockStart,
120
128
  uint256 newTransferLockEnd
121
129
  ) public virtual override onlyOwner {
122
- require(transferLockEnabled, LSP8CannotUpdateTransferLockPeriod());
130
+ require(nonTransferabilityEnabled, LSP8CannotUpdateTransferLockPeriod());
123
131
 
124
132
  // When transferLockEnd is 0, it means no end time is set (transfers locked indefinitely after transferLockStart)
125
133
  // When transferLockStart is 0, it means no start time is set (transfers locked up until transferLockEnd)
@@ -134,6 +142,7 @@ abstract contract LSP8NonTransferableAbstract is
134
142
  transferLockEnd = newTransferLockEnd;
135
143
 
136
144
  emit TransferLockPeriodChanged({
145
+ nonTransferabilityEnabled: true,
137
146
  start: newTransferLockStart,
138
147
  end: newTransferLockEnd
139
148
  });
@@ -42,7 +42,7 @@ abstract contract LSP8NonTransferableInitAbstract is
42
42
  uint256 public transferLockEnd;
43
43
 
44
44
  /// @inheritdoc ILSP8NonTransferable
45
- bool public transferLockEnabled;
45
+ bool public nonTransferabilityEnabled;
46
46
 
47
47
  /// @notice Initializes the LSP8NonTransferable contract with base token params and transfer settings.
48
48
  /// @dev Initializes the LSP8IdentifiableDigitalAsset base, the access control layer and transfer settings.
@@ -90,9 +90,13 @@ abstract contract LSP8NonTransferableInitAbstract is
90
90
  );
91
91
  transferLockStart = transferLockStart_;
92
92
  transferLockEnd = transferLockEnd_;
93
- transferLockEnabled = true;
93
+ nonTransferabilityEnabled = true;
94
94
 
95
- emit TransferLockPeriodChanged(transferLockStart_, transferLockEnd_);
95
+ emit TransferLockPeriodChanged({
96
+ nonTransferabilityEnabled: true,
97
+ start: transferLockStart_,
98
+ end: transferLockEnd_
99
+ });
96
100
  _grantRole(NON_TRANSFERABLE_BYPASS_ROLE, owner());
97
101
  }
98
102
 
@@ -119,7 +123,7 @@ abstract contract LSP8NonTransferableInitAbstract is
119
123
  // solhint-disable not-rely-on-time
120
124
  // Transfer-lock windows are inherently time-based; `block.timestamp` is the intended source.
121
125
  function isTransferable() public view virtual override returns (bool) {
122
- if (!transferLockEnabled) return true;
126
+ if (!nonTransferabilityEnabled) return true;
123
127
 
124
128
  bool isTransferLockStartEnabled = transferLockStart != 0;
125
129
  bool isTransferLockEndEnabled = transferLockEnd != 0;
@@ -149,13 +153,17 @@ abstract contract LSP8NonTransferableInitAbstract is
149
153
  /// @inheritdoc ILSP8NonTransferable
150
154
  /// @custom:info The list of addresses holding the `NON_TRANSFERABLE_BYPASS_ROLE` remains populated after the non-transferable feature is switched off.
151
155
  function makeTransferable() public virtual override onlyOwner {
152
- require(transferLockEnabled, LSP8TokenAlreadyTransferable());
156
+ require(nonTransferabilityEnabled, LSP8TokenAlreadyTransferable());
153
157
 
154
- transferLockEnabled = false;
158
+ nonTransferabilityEnabled = false;
155
159
  transferLockStart = 0;
156
160
  transferLockEnd = 0;
157
161
 
158
- emit TransferLockPeriodChanged({start: 0, end: 0});
162
+ emit TransferLockPeriodChanged({
163
+ nonTransferabilityEnabled: false,
164
+ start: 0,
165
+ end: 0
166
+ });
159
167
  }
160
168
 
161
169
  /// @inheritdoc ILSP8NonTransferable
@@ -163,7 +171,7 @@ abstract contract LSP8NonTransferableInitAbstract is
163
171
  uint256 newTransferLockStart,
164
172
  uint256 newTransferLockEnd
165
173
  ) public virtual override onlyOwner {
166
- require(transferLockEnabled, LSP8CannotUpdateTransferLockPeriod());
174
+ require(nonTransferabilityEnabled, LSP8CannotUpdateTransferLockPeriod());
167
175
 
168
176
  // When transferLockEnd is 0, it means no end time is set (transfers locked indefinitely after transferLockStart)
169
177
  // When transferLockStart is 0, it means no start time is set (transfers locked up until transferLockEnd)
@@ -178,6 +186,7 @@ abstract contract LSP8NonTransferableInitAbstract is
178
186
  transferLockEnd = newTransferLockEnd;
179
187
 
180
188
  emit TransferLockPeriodChanged({
189
+ nonTransferabilityEnabled: true,
181
190
  start: newTransferLockStart,
182
191
  end: newTransferLockEnd
183
192
  });
@@ -9,6 +9,15 @@ interface ILSP8Revokable {
9
9
  /// @dev Emitted when revokable status is changed.
10
10
  event RevokableStatusChanged(bool indexed enabled);
11
11
 
12
+ /// @dev Emitted when a token is revoked from a holder.
13
+ event TokenRevoked(
14
+ address indexed revoker,
15
+ address indexed from,
16
+ address indexed to,
17
+ bytes32 tokenId,
18
+ bytes data
19
+ );
20
+
12
21
  /// @notice Returns whether the feature to revoke tokens from users is enabled or not.
13
22
  function isRevokable() external view returns (bool);
14
23
 
@@ -75,6 +75,14 @@ abstract contract LSP8RevokableAbstract is
75
75
  AccessControlUnauthorizedAccount(to, REVOKER_ROLE)
76
76
  );
77
77
 
78
+ emit TokenRevoked({
79
+ revoker: msg.sender,
80
+ from: from,
81
+ to: to,
82
+ tokenId: tokenId,
83
+ data: data
84
+ });
85
+
78
86
  // We assume revokers are trusted when specifying revocation destinations.
79
87
  // Therefore, we bypass LSP1 receiver checks.
80
88
  _transfer({
@@ -109,9 +109,23 @@ abstract contract LSP8RevokableInitAbstract is
109
109
  AccessControlUnauthorizedAccount(to, REVOKER_ROLE)
110
110
  );
111
111
 
112
+ emit TokenRevoked({
113
+ revoker: msg.sender,
114
+ from: from,
115
+ to: to,
116
+ tokenId: tokenId,
117
+ data: data
118
+ });
119
+
112
120
  // We assume revokers are trusted when specifying revocation destinations.
113
121
  // Therefore, we bypass LSP1 receiver checks.
114
- _transfer(from, to, tokenId, true, data);
122
+ _transfer({
123
+ from: from,
124
+ to: to,
125
+ tokenId: tokenId,
126
+ force: true,
127
+ data: data
128
+ });
115
129
  }
116
130
 
117
131
  function supportsInterface(