@kub-chain/contracts 1.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/README.md +88 -0
- package/contracts/access/AccessController.sol +96 -0
- package/contracts/access/AccessControllerKAP.sol +116 -0
- package/contracts/access/Authorization.sol +36 -0
- package/contracts/access/AuthorizationKAP.sol +60 -0
- package/contracts/access/Committee.sol +26 -0
- package/contracts/access/Ownable.sol +39 -0
- package/contracts/interfaces/IAdminProjectRouter.sol +9 -0
- package/contracts/interfaces/IKYCBitkubChain.sol +8 -0
- package/contracts/kyc/KYCHandler.sol +24 -0
- package/contracts/libs/Address.sol +16 -0
- package/contracts/libs/EnumerableSetAddress.sol +70 -0
- package/contracts/libs/EnumerableSetUint.sol +74 -0
- package/contracts/libs/EnumerateMap.sol +136 -0
- package/contracts/libs/String.sol +26 -0
- package/contracts/token/KAP-1155/KAP1155.sol +493 -0
- package/contracts/token/KAP-1155/interfaces/IKAP1155.sol +69 -0
- package/contracts/token/KAP-1155/interfaces/IKAP1155Enumerable.sol +7 -0
- package/contracts/token/KAP-1155/interfaces/IKAP1155Metadata.sol +12 -0
- package/contracts/token/KAP-1155/interfaces/IKAP1155Receiver.sol +20 -0
- package/contracts/token/KAP-20/KAP20.sol +276 -0
- package/contracts/token/KAP-20/interfaces/IKAP20.sol +43 -0
- package/contracts/token/KAP-20/interfaces/IKToken.sol +17 -0
- package/contracts/token/KAP-22/KAP22.sol +358 -0
- package/contracts/token/KAP-22/interfaces/IKAP22.sol +23 -0
- package/contracts/token/KAP-22/utils/TransferRouter.sol +29 -0
- package/contracts/token/KAP-22/utils/WhitelistAddress.sol +35 -0
- package/contracts/token/KAP-721/KAP721.sol +416 -0
- package/contracts/token/KAP-721/interfaces/IKAP721.sol +60 -0
- package/contracts/token/KAP-721/interfaces/IKAP721Enumerable.sol +10 -0
- package/contracts/token/KAP-721/interfaces/IKAP721Metadata.sol +10 -0
- package/contracts/token/KAP-721/interfaces/IKAP721Receiver.sol +11 -0
- package/contracts/token/KAP-721/interfaces/IKAP721V2.sol +20 -0
- package/contracts/utils/Context.sol +13 -0
- package/contracts/utils/Pausable.sol +34 -0
- package/contracts/utils/introspections/IKAP165.sol +6 -0
- package/contracts/utils/introspections/KAP165.sol +12 -0
- package/package.json +26 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity >=0.6.0;
|
|
3
|
+
|
|
4
|
+
library EnumerableMap {
|
|
5
|
+
struct MapEntry {
|
|
6
|
+
bytes32 _key;
|
|
7
|
+
bytes32 _value;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
struct Map {
|
|
11
|
+
MapEntry[] _entries;
|
|
12
|
+
mapping(bytes32 => uint256) _indexes;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function _set(
|
|
16
|
+
Map storage map,
|
|
17
|
+
bytes32 key,
|
|
18
|
+
bytes32 value
|
|
19
|
+
) private returns (bool) {
|
|
20
|
+
uint256 keyIndex = map._indexes[key];
|
|
21
|
+
|
|
22
|
+
if (keyIndex == 0) {
|
|
23
|
+
map._entries.push(MapEntry({ _key: key, _value: value }));
|
|
24
|
+
map._indexes[key] = map._entries.length;
|
|
25
|
+
return true;
|
|
26
|
+
} else {
|
|
27
|
+
map._entries[keyIndex - 1]._value = value;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function _remove(Map storage map, bytes32 key) private returns (bool) {
|
|
33
|
+
uint256 keyIndex = map._indexes[key];
|
|
34
|
+
|
|
35
|
+
if (keyIndex != 0) {
|
|
36
|
+
uint256 toDeleteIndex = keyIndex - 1;
|
|
37
|
+
uint256 lastIndex = map._entries.length - 1;
|
|
38
|
+
|
|
39
|
+
MapEntry storage lastEntry = map._entries[lastIndex];
|
|
40
|
+
|
|
41
|
+
map._entries[toDeleteIndex] = lastEntry;
|
|
42
|
+
map._indexes[lastEntry._key] = toDeleteIndex + 1;
|
|
43
|
+
|
|
44
|
+
map._entries.pop();
|
|
45
|
+
|
|
46
|
+
delete map._indexes[key];
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
} else {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function _contains(Map storage map, bytes32 key) private view returns (bool) {
|
|
55
|
+
return map._indexes[key] != 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function _length(Map storage map) private view returns (uint256) {
|
|
59
|
+
return map._entries.length;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
|
|
63
|
+
require(map._entries.length > index, "EnumerableMap: index out of bounds");
|
|
64
|
+
|
|
65
|
+
MapEntry storage entry = map._entries[index];
|
|
66
|
+
return (entry._key, entry._value);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
|
|
70
|
+
uint256 keyIndex = map._indexes[key];
|
|
71
|
+
if (keyIndex == 0) return (false, 0);
|
|
72
|
+
return (true, map._entries[keyIndex - 1]._value);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
|
|
76
|
+
uint256 keyIndex = map._indexes[key];
|
|
77
|
+
require(keyIndex != 0, "EnumerableMap: nonexistent key");
|
|
78
|
+
return map._entries[keyIndex - 1]._value;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function _get(
|
|
82
|
+
Map storage map,
|
|
83
|
+
bytes32 key,
|
|
84
|
+
string memory errorMessage
|
|
85
|
+
) private view returns (bytes32) {
|
|
86
|
+
uint256 keyIndex = map._indexes[key];
|
|
87
|
+
require(keyIndex != 0, errorMessage);
|
|
88
|
+
return map._entries[keyIndex - 1]._value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
struct UintToAddressMap {
|
|
92
|
+
Map _inner;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function set(
|
|
96
|
+
UintToAddressMap storage map,
|
|
97
|
+
uint256 key,
|
|
98
|
+
address value
|
|
99
|
+
) internal returns (bool) {
|
|
100
|
+
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
|
|
104
|
+
return _remove(map._inner, bytes32(key));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
|
|
108
|
+
return _contains(map._inner, bytes32(key));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function length(UintToAddressMap storage map) internal view returns (uint256) {
|
|
112
|
+
return _length(map._inner);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
|
|
116
|
+
(bytes32 key, bytes32 value) = _at(map._inner, index);
|
|
117
|
+
return (uint256(key), address(uint160(uint256(value))));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
|
|
121
|
+
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
|
|
122
|
+
return (success, address(uint160(uint256(value))));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
|
|
126
|
+
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function get(
|
|
130
|
+
UintToAddressMap storage map,
|
|
131
|
+
uint256 key,
|
|
132
|
+
string memory errorMessage
|
|
133
|
+
) internal view returns (address) {
|
|
134
|
+
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
library Strings {
|
|
5
|
+
function toString(uint256 value) internal pure returns (string memory) {
|
|
6
|
+
// Inspired by OraclizeAPI's implementation - MIT licence
|
|
7
|
+
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
|
|
8
|
+
|
|
9
|
+
if (value == 0) {
|
|
10
|
+
return "0";
|
|
11
|
+
}
|
|
12
|
+
uint256 temp = value;
|
|
13
|
+
uint256 digits;
|
|
14
|
+
while (temp != 0) {
|
|
15
|
+
digits++;
|
|
16
|
+
temp /= 10;
|
|
17
|
+
}
|
|
18
|
+
bytes memory buffer = new bytes(digits);
|
|
19
|
+
while (value != 0) {
|
|
20
|
+
digits -= 1;
|
|
21
|
+
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
|
|
22
|
+
value /= 10;
|
|
23
|
+
}
|
|
24
|
+
return string(buffer);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Sources flattened with hardhat v2.5.0 https://hardhat.org
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import {KAP165, IKAP165} from "../../utils/introspections/KAP165.sol";
|
|
7
|
+
import {IAdminProjectRouter} from "../../interfaces/IAdminProjectRouter.sol";
|
|
8
|
+
import {IKYCBitkubChain} from "../../interfaces/IKYCBitkubChain.sol";
|
|
9
|
+
import {KYCHandler} from "../../kyc/KYCHandler.sol";
|
|
10
|
+
import {AuthorizationKAP} from "../../access/AuthorizationKAP.sol";
|
|
11
|
+
import {Pausable} from "../../utils/Pausable.sol";
|
|
12
|
+
import {IKAP1155} from "./interfaces/IKAP1155.sol";
|
|
13
|
+
import {IKAP1155Metadata} from "./interfaces/IKAP1155Metadata.sol";
|
|
14
|
+
import {IKAP1155Enumerable} from "./interfaces/IKAP1155Enumerable.sol";
|
|
15
|
+
import {IKAP1155Receiver} from "./interfaces/IKAP1155Receiver.sol";
|
|
16
|
+
import {Address} from "../../libs/Address.sol";
|
|
17
|
+
import {Strings} from "../../libs/String.sol";
|
|
18
|
+
import {EnumerableSetUint} from "../../libs/EnumerableSetUint.sol";
|
|
19
|
+
|
|
20
|
+
abstract contract KAP1155 is
|
|
21
|
+
IKAP1155,
|
|
22
|
+
IKAP1155Metadata,
|
|
23
|
+
IKAP1155Enumerable,
|
|
24
|
+
KAP165,
|
|
25
|
+
AuthorizationKAP,
|
|
26
|
+
KYCHandler,
|
|
27
|
+
Pausable
|
|
28
|
+
{
|
|
29
|
+
using Address for address;
|
|
30
|
+
using Strings for uint256;
|
|
31
|
+
|
|
32
|
+
// Token name
|
|
33
|
+
string public override name;
|
|
34
|
+
|
|
35
|
+
// Token symbol
|
|
36
|
+
string public override symbol;
|
|
37
|
+
|
|
38
|
+
// Base URI
|
|
39
|
+
string public baseURI;
|
|
40
|
+
|
|
41
|
+
// Base KAP URI
|
|
42
|
+
string public baseKapURI;
|
|
43
|
+
|
|
44
|
+
// Mapping from token ID to account balances
|
|
45
|
+
mapping(uint256 => mapping(address => uint256)) internal _balances;
|
|
46
|
+
|
|
47
|
+
// Mapping from account to operator approvals
|
|
48
|
+
mapping(address => mapping(address => bool)) private _operatorApprovals;
|
|
49
|
+
|
|
50
|
+
// Mapping from ID to totalSupply
|
|
51
|
+
mapping(uint256 => uint256) public totalSupplyById;
|
|
52
|
+
|
|
53
|
+
// Mapping from ID to uri
|
|
54
|
+
mapping(uint256 => string) private _tokenURIs;
|
|
55
|
+
|
|
56
|
+
// Mapping for kap URIs
|
|
57
|
+
mapping(uint256 => string) private _kapURIs;
|
|
58
|
+
|
|
59
|
+
// Total supply
|
|
60
|
+
uint256 public override totalSupply;
|
|
61
|
+
|
|
62
|
+
constructor(
|
|
63
|
+
string memory name_,
|
|
64
|
+
string memory symbol_,
|
|
65
|
+
address adminRouter_,
|
|
66
|
+
address kyc_,
|
|
67
|
+
address committee_,
|
|
68
|
+
uint256 acceptedKycLevel_
|
|
69
|
+
) {
|
|
70
|
+
name = name_;
|
|
71
|
+
symbol = symbol_;
|
|
72
|
+
adminRouter = IAdminProjectRouter(adminRouter_);
|
|
73
|
+
kyc = IKYCBitkubChain(kyc_);
|
|
74
|
+
committee = committee_;
|
|
75
|
+
acceptedKYCLevel = acceptedKycLevel_;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function activateOnlyKYCAddress() public onlyCommittee {
|
|
79
|
+
_activateOnlyKYCAddress();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function setKYC(IKYCBitkubChain _kyc) public onlyCommittee {
|
|
83
|
+
_setKYC(_kyc);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function setAcceptedKYCLevel(uint256 _kycLevel) public onlyCommittee {
|
|
87
|
+
_setAcceptedKYCLevel(_kycLevel);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function pause() public onlyCommittee {
|
|
91
|
+
_pause();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function unpause() public onlyCommittee {
|
|
95
|
+
_unpause();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override(KAP165, IKAP165) returns (bool) {
|
|
99
|
+
return
|
|
100
|
+
interfaceId == type(IKAP1155).interfaceId ||
|
|
101
|
+
interfaceId == type(IKAP1155Metadata).interfaceId ||
|
|
102
|
+
interfaceId == type(IKAP1155Enumerable).interfaceId ||
|
|
103
|
+
super.supportsInterface(interfaceId);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function exists(uint256 id) public view virtual returns (bool) {
|
|
107
|
+
return totalSupplyById[id] > 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function uri(uint256 tokenId) public view virtual override returns (string memory) {
|
|
111
|
+
require(totalSupplyById[tokenId] > 0, "KAP1155: URI query for nonexistent token");
|
|
112
|
+
|
|
113
|
+
string memory _tokenURI = _tokenURIs[tokenId];
|
|
114
|
+
|
|
115
|
+
// If there is no base URI, return the token URI.
|
|
116
|
+
if (bytes(baseURI).length == 0) {
|
|
117
|
+
return _tokenURI;
|
|
118
|
+
}
|
|
119
|
+
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
|
|
120
|
+
if (bytes(_tokenURI).length > 0) {
|
|
121
|
+
return string(abi.encodePacked(baseURI, _tokenURI));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
|
|
125
|
+
return string(abi.encodePacked(baseURI, tokenId.toString()));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function kapURI(uint256 tokenId) public view virtual override returns (string memory) {
|
|
129
|
+
require(totalSupplyById[tokenId] > 0, "KAP1155: URI query for nonexistent token");
|
|
130
|
+
|
|
131
|
+
string memory _kapURI = _kapURIs[tokenId];
|
|
132
|
+
|
|
133
|
+
// If there is no base KAP URI, return the kapURI.
|
|
134
|
+
if (bytes(baseKapURI).length == 0) {
|
|
135
|
+
return _kapURI;
|
|
136
|
+
}
|
|
137
|
+
// If both are set, concatenate the base KAP URI and kapURI (via abi.encodePacked).
|
|
138
|
+
if (bytes(_kapURI).length > 0) {
|
|
139
|
+
return string(abi.encodePacked(baseKapURI, _kapURI));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// If there is a base KAP URI but no kapURI, concatenate the tokenID to the base KAP URI.
|
|
143
|
+
return string(abi.encodePacked(baseKapURI, tokenId.toString()));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
|
|
147
|
+
require(account != address(0), "KAP1155: balance query for the zero address");
|
|
148
|
+
return _balances[id][account];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
|
|
152
|
+
public
|
|
153
|
+
view
|
|
154
|
+
virtual
|
|
155
|
+
override
|
|
156
|
+
returns (uint256[] memory)
|
|
157
|
+
{
|
|
158
|
+
require(accounts.length == ids.length, "KAP1155: accounts and ids length mismatch");
|
|
159
|
+
|
|
160
|
+
uint256[] memory batchBalances = new uint256[](accounts.length);
|
|
161
|
+
|
|
162
|
+
for (uint256 i = 0; i < accounts.length; ++i) {
|
|
163
|
+
batchBalances[i] = balanceOf(accounts[i], ids[i]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return batchBalances;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function setApprovalForAll(address operator, bool approved) public virtual override {
|
|
170
|
+
require(msg.sender != operator, "KAP1155: setting approval status for self");
|
|
171
|
+
|
|
172
|
+
_operatorApprovals[msg.sender][operator] = approved;
|
|
173
|
+
emit ApprovalForAll(msg.sender, operator, approved);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
|
|
177
|
+
return _operatorApprovals[account][operator];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function adminTransfer(
|
|
181
|
+
address sender,
|
|
182
|
+
address recipient,
|
|
183
|
+
uint256 id,
|
|
184
|
+
uint256 amount
|
|
185
|
+
) external override onlyCommittee {
|
|
186
|
+
_safeTransferFrom(sender, recipient, id, amount, "");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function internalTransfer(
|
|
190
|
+
address sender,
|
|
191
|
+
address recipient,
|
|
192
|
+
uint256 id,
|
|
193
|
+
uint256 amount
|
|
194
|
+
) external override onlySuperAdminOrTransferRouter whenNotPaused returns (bool) {
|
|
195
|
+
require(
|
|
196
|
+
kyc.kycsLevel(sender) >= acceptedKYCLevel && kyc.kycsLevel(recipient) >= acceptedKYCLevel,
|
|
197
|
+
"KAP1155: only internal purpose"
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
_safeTransferFrom(sender, recipient, id, amount, "");
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function externalTransfer(
|
|
205
|
+
address sender,
|
|
206
|
+
address recipient,
|
|
207
|
+
uint256 id,
|
|
208
|
+
uint256 amount
|
|
209
|
+
) external override onlySuperAdminOrTransferRouter whenNotPaused returns (bool) {
|
|
210
|
+
require(kyc.kycsLevel(sender) >= acceptedKYCLevel, "KAP1155: only external purpose");
|
|
211
|
+
|
|
212
|
+
_safeTransferFrom(sender, recipient, id, amount, "");
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function safeTransferFrom(
|
|
217
|
+
address from,
|
|
218
|
+
address to,
|
|
219
|
+
uint256 id,
|
|
220
|
+
uint256 amount,
|
|
221
|
+
bytes memory data
|
|
222
|
+
) public virtual override whenNotPaused {
|
|
223
|
+
require(from == msg.sender || isApprovedForAll(from, msg.sender), "KAP1155: caller is not owner nor approved");
|
|
224
|
+
_safeTransferFrom(from, to, id, amount, data);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function safeBatchTransferFrom(
|
|
228
|
+
address from,
|
|
229
|
+
address to,
|
|
230
|
+
uint256[] memory ids,
|
|
231
|
+
uint256[] memory amounts,
|
|
232
|
+
bytes memory data
|
|
233
|
+
) public virtual override whenNotPaused {
|
|
234
|
+
require(
|
|
235
|
+
from == msg.sender || isApprovedForAll(from, msg.sender),
|
|
236
|
+
"KAP1155: transfer caller is not owner nor approved"
|
|
237
|
+
);
|
|
238
|
+
_safeBatchTransferFrom(from, to, ids, amounts, data);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function _safeTransferFrom(
|
|
242
|
+
address from,
|
|
243
|
+
address to,
|
|
244
|
+
uint256 id,
|
|
245
|
+
uint256 amount,
|
|
246
|
+
bytes memory data
|
|
247
|
+
) internal virtual {
|
|
248
|
+
require(to != address(0), "KAP1155: transfer to the zero address");
|
|
249
|
+
|
|
250
|
+
address operator = msg.sender;
|
|
251
|
+
|
|
252
|
+
_beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
|
|
253
|
+
|
|
254
|
+
uint256 fromBalance = _balances[id][from];
|
|
255
|
+
require(fromBalance >= amount, "KAP1155: insufficient balance for transfer");
|
|
256
|
+
unchecked {
|
|
257
|
+
_balances[id][from] = fromBalance - amount;
|
|
258
|
+
}
|
|
259
|
+
_balances[id][to] += amount;
|
|
260
|
+
|
|
261
|
+
emit TransferSingle(operator, from, to, id, amount);
|
|
262
|
+
|
|
263
|
+
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function _safeBatchTransferFrom(
|
|
267
|
+
address from,
|
|
268
|
+
address to,
|
|
269
|
+
uint256[] memory ids,
|
|
270
|
+
uint256[] memory amounts,
|
|
271
|
+
bytes memory data
|
|
272
|
+
) internal virtual {
|
|
273
|
+
require(ids.length == amounts.length, "KAP1155: ids and amounts length mismatch");
|
|
274
|
+
require(to != address(0), "KAP1155: transfer to the zero address");
|
|
275
|
+
|
|
276
|
+
address operator = msg.sender;
|
|
277
|
+
|
|
278
|
+
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
|
|
279
|
+
|
|
280
|
+
for (uint256 i = 0; i < ids.length; ++i) {
|
|
281
|
+
uint256 id = ids[i];
|
|
282
|
+
uint256 amount = amounts[i];
|
|
283
|
+
|
|
284
|
+
uint256 fromBalance = _balances[id][from];
|
|
285
|
+
require(fromBalance >= amount, "KAP1155: insufficient balance for transfer");
|
|
286
|
+
unchecked {
|
|
287
|
+
_balances[id][from] = fromBalance - amount;
|
|
288
|
+
}
|
|
289
|
+
_balances[id][to] += amount;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
emit TransferBatch(operator, from, to, ids, amounts);
|
|
293
|
+
|
|
294
|
+
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function _mint(
|
|
298
|
+
address account,
|
|
299
|
+
uint256 id,
|
|
300
|
+
uint256 amount,
|
|
301
|
+
bytes memory data
|
|
302
|
+
) internal virtual {
|
|
303
|
+
require(account != address(0), "KAP1155: mint to the zero address");
|
|
304
|
+
|
|
305
|
+
address operator = msg.sender;
|
|
306
|
+
|
|
307
|
+
_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
|
|
308
|
+
|
|
309
|
+
_balances[id][account] += amount;
|
|
310
|
+
totalSupply += amount;
|
|
311
|
+
totalSupplyById[id] += amount;
|
|
312
|
+
|
|
313
|
+
emit TransferSingle(operator, address(0), account, id, amount);
|
|
314
|
+
|
|
315
|
+
_doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function _mintBatch(
|
|
319
|
+
address to,
|
|
320
|
+
uint256[] memory ids,
|
|
321
|
+
uint256[] memory amounts,
|
|
322
|
+
bytes memory data
|
|
323
|
+
) internal virtual {
|
|
324
|
+
require(to != address(0), "KAP1155: mint to the zero address");
|
|
325
|
+
require(ids.length == amounts.length, "KAP1155: ids and amounts length mismatch");
|
|
326
|
+
|
|
327
|
+
address operator = msg.sender;
|
|
328
|
+
|
|
329
|
+
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
|
|
330
|
+
|
|
331
|
+
for (uint256 i = 0; i < ids.length; i++) {
|
|
332
|
+
_balances[ids[i]][to] += amounts[i];
|
|
333
|
+
totalSupply += amounts[i];
|
|
334
|
+
totalSupplyById[ids[i]] += amounts[i];
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
emit TransferBatch(operator, address(0), to, ids, amounts);
|
|
338
|
+
|
|
339
|
+
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function _burn(
|
|
343
|
+
address account,
|
|
344
|
+
uint256 id,
|
|
345
|
+
uint256 amount
|
|
346
|
+
) internal virtual {
|
|
347
|
+
require(account != address(0), "KAP1155: burn from the zero address");
|
|
348
|
+
|
|
349
|
+
address operator = msg.sender;
|
|
350
|
+
|
|
351
|
+
_beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
|
|
352
|
+
|
|
353
|
+
uint256 accountBalance = _balances[id][account];
|
|
354
|
+
require(accountBalance >= amount, "KAP1155: burn amount exceeds balance");
|
|
355
|
+
unchecked {
|
|
356
|
+
_balances[id][account] = accountBalance - amount;
|
|
357
|
+
}
|
|
358
|
+
totalSupply -= amount;
|
|
359
|
+
totalSupplyById[id] -= amount;
|
|
360
|
+
|
|
361
|
+
if (totalSupplyById[id] == 0) {
|
|
362
|
+
// Clear metadata (if any)
|
|
363
|
+
if (bytes(_tokenURIs[id]).length != 0) {
|
|
364
|
+
delete _tokenURIs[id];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Clear metadata (if any)
|
|
368
|
+
if (bytes(_kapURIs[id]).length != 0) {
|
|
369
|
+
delete _kapURIs[id];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
emit TransferSingle(operator, account, address(0), id, amount);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function _burnBatch(
|
|
377
|
+
address account,
|
|
378
|
+
uint256[] memory ids,
|
|
379
|
+
uint256[] memory amounts
|
|
380
|
+
) internal virtual {
|
|
381
|
+
require(account != address(0), "KAP1155: burn from the zero address");
|
|
382
|
+
require(ids.length == amounts.length, "KAP1155: ids and amounts length mismatch");
|
|
383
|
+
|
|
384
|
+
address operator = msg.sender;
|
|
385
|
+
|
|
386
|
+
_beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
|
|
387
|
+
|
|
388
|
+
for (uint256 i = 0; i < ids.length; i++) {
|
|
389
|
+
uint256 id = ids[i];
|
|
390
|
+
uint256 amount = amounts[i];
|
|
391
|
+
|
|
392
|
+
uint256 accountBalance = _balances[id][account];
|
|
393
|
+
require(accountBalance >= amount, "KAP1155: burn amount exceeds balance");
|
|
394
|
+
unchecked {
|
|
395
|
+
_balances[id][account] = accountBalance - amount;
|
|
396
|
+
}
|
|
397
|
+
totalSupply -= amount;
|
|
398
|
+
totalSupplyById[id] -= amount;
|
|
399
|
+
|
|
400
|
+
if (totalSupplyById[id] == 0) {
|
|
401
|
+
// Clear metadata (if any)
|
|
402
|
+
if (bytes(_tokenURIs[id]).length != 0) {
|
|
403
|
+
delete _tokenURIs[id];
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Clear metadata (if any)
|
|
407
|
+
if (bytes(_kapURIs[id]).length != 0) {
|
|
408
|
+
delete _kapURIs[id];
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
emit TransferBatch(operator, account, address(0), ids, amounts);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function _beforeTokenTransfer(
|
|
417
|
+
address operator,
|
|
418
|
+
address from,
|
|
419
|
+
address to,
|
|
420
|
+
uint256[] memory ids,
|
|
421
|
+
uint256[] memory amounts,
|
|
422
|
+
bytes memory data
|
|
423
|
+
) internal virtual {}
|
|
424
|
+
|
|
425
|
+
function _doSafeTransferAcceptanceCheck(
|
|
426
|
+
address operator,
|
|
427
|
+
address from,
|
|
428
|
+
address to,
|
|
429
|
+
uint256 id,
|
|
430
|
+
uint256 amount,
|
|
431
|
+
bytes memory data
|
|
432
|
+
) internal {
|
|
433
|
+
if (to.isContract()) {
|
|
434
|
+
try IKAP1155Receiver(to).onKAP1155Received(operator, from, id, amount, data) returns (bytes4 response) {
|
|
435
|
+
if (response != IKAP1155Receiver.onKAP1155Received.selector) {
|
|
436
|
+
revert("KAP1155: KAP1155Receiver rejected tokens");
|
|
437
|
+
}
|
|
438
|
+
} catch Error(string memory reason) {
|
|
439
|
+
revert(reason);
|
|
440
|
+
} catch {
|
|
441
|
+
revert("KAP1155: transfer to non KAP1155Receiver implementer");
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function _doSafeBatchTransferAcceptanceCheck(
|
|
447
|
+
address operator,
|
|
448
|
+
address from,
|
|
449
|
+
address to,
|
|
450
|
+
uint256[] memory ids,
|
|
451
|
+
uint256[] memory amounts,
|
|
452
|
+
bytes memory data
|
|
453
|
+
) internal {
|
|
454
|
+
if (to.isContract()) {
|
|
455
|
+
try IKAP1155Receiver(to).onKAP1155BatchReceived(operator, from, ids, amounts, data) returns (
|
|
456
|
+
bytes4 response
|
|
457
|
+
) {
|
|
458
|
+
if (response != IKAP1155Receiver.onKAP1155BatchReceived.selector) {
|
|
459
|
+
revert("KAP1155: KAP1155Receiver rejected tokens");
|
|
460
|
+
}
|
|
461
|
+
} catch Error(string memory reason) {
|
|
462
|
+
revert(reason);
|
|
463
|
+
} catch {
|
|
464
|
+
revert("KAP1155: transfer to non KAP1155Receiver implementer");
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function _setURI(uint256 tokenId, string memory _tokenURI) internal virtual {
|
|
470
|
+
require(totalSupplyById[tokenId] > 0, "KAP1155: URI query for nonexistent token");
|
|
471
|
+
_tokenURIs[tokenId] = _tokenURI;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function _setBaseURI(string memory _baseURI) internal virtual {
|
|
475
|
+
baseURI = _baseURI;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function _setKapURI(uint256 tokenId, string memory _kapURI) internal virtual {
|
|
479
|
+
require(totalSupplyById[tokenId] > 0, "KAP1155: URI query for nonexistent token");
|
|
480
|
+
_kapURIs[tokenId] = _kapURI;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function _setBaseKapURI(string memory baseKapURI_) internal virtual {
|
|
484
|
+
baseKapURI = baseKapURI_;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function _asSingletonArray(uint256 element) internal pure returns (uint256[] memory) {
|
|
488
|
+
uint256[] memory array = new uint256[](1);
|
|
489
|
+
array[0] = element;
|
|
490
|
+
|
|
491
|
+
return array;
|
|
492
|
+
}
|
|
493
|
+
}
|