@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.
Files changed (38) hide show
  1. package/README.md +88 -0
  2. package/contracts/access/AccessController.sol +96 -0
  3. package/contracts/access/AccessControllerKAP.sol +116 -0
  4. package/contracts/access/Authorization.sol +36 -0
  5. package/contracts/access/AuthorizationKAP.sol +60 -0
  6. package/contracts/access/Committee.sol +26 -0
  7. package/contracts/access/Ownable.sol +39 -0
  8. package/contracts/interfaces/IAdminProjectRouter.sol +9 -0
  9. package/contracts/interfaces/IKYCBitkubChain.sol +8 -0
  10. package/contracts/kyc/KYCHandler.sol +24 -0
  11. package/contracts/libs/Address.sol +16 -0
  12. package/contracts/libs/EnumerableSetAddress.sol +70 -0
  13. package/contracts/libs/EnumerableSetUint.sol +74 -0
  14. package/contracts/libs/EnumerateMap.sol +136 -0
  15. package/contracts/libs/String.sol +26 -0
  16. package/contracts/token/KAP-1155/KAP1155.sol +493 -0
  17. package/contracts/token/KAP-1155/interfaces/IKAP1155.sol +69 -0
  18. package/contracts/token/KAP-1155/interfaces/IKAP1155Enumerable.sol +7 -0
  19. package/contracts/token/KAP-1155/interfaces/IKAP1155Metadata.sol +12 -0
  20. package/contracts/token/KAP-1155/interfaces/IKAP1155Receiver.sol +20 -0
  21. package/contracts/token/KAP-20/KAP20.sol +276 -0
  22. package/contracts/token/KAP-20/interfaces/IKAP20.sol +43 -0
  23. package/contracts/token/KAP-20/interfaces/IKToken.sol +17 -0
  24. package/contracts/token/KAP-22/KAP22.sol +358 -0
  25. package/contracts/token/KAP-22/interfaces/IKAP22.sol +23 -0
  26. package/contracts/token/KAP-22/utils/TransferRouter.sol +29 -0
  27. package/contracts/token/KAP-22/utils/WhitelistAddress.sol +35 -0
  28. package/contracts/token/KAP-721/KAP721.sol +416 -0
  29. package/contracts/token/KAP-721/interfaces/IKAP721.sol +60 -0
  30. package/contracts/token/KAP-721/interfaces/IKAP721Enumerable.sol +10 -0
  31. package/contracts/token/KAP-721/interfaces/IKAP721Metadata.sol +10 -0
  32. package/contracts/token/KAP-721/interfaces/IKAP721Receiver.sol +11 -0
  33. package/contracts/token/KAP-721/interfaces/IKAP721V2.sol +20 -0
  34. package/contracts/utils/Context.sol +13 -0
  35. package/contracts/utils/Pausable.sol +34 -0
  36. package/contracts/utils/introspections/IKAP165.sol +6 -0
  37. package/contracts/utils/introspections/KAP165.sol +12 -0
  38. package/package.json +26 -0
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # KUB Contracts
2
+
3
+ A library of Solidity smart contracts implementing the **KAP token standards** and supporting access-control, KYC, and utility primitives for the [KUB](https://kubchain.com/) ecosystem.
4
+
5
+ ## Overview
6
+
7
+ This repository provides reusable, abstract base contracts for building KAP-compliant tokens and applications on KUB:
8
+
9
+ - **KAP token standards** - fungible (KAP-20, KAP-22), non-fungible (KAP-721), and multi-token (KAP-1155) implementations.
10
+ - **Access control** — owner, committee, and project-router-based authorization models.
11
+ - **KYC integration** — hooks into KUB's on-chain KYC registry to enforce KYC-level requirements.
12
+ - **Utilities & libraries** — pausing, introspection (KAP-165), and gas-efficient enumerable data structures.
13
+
14
+ All contracts target Solidity `^0.8.0` and are released under the MIT license.
15
+
16
+ ## Repository structure
17
+
18
+ ```
19
+ contracts/
20
+ ├── token/
21
+ │ ├── KAP-20/ Fungible token standard (ERC-20-like) with KYC + admin routing
22
+ │ ├── KAP-22/ Period/stamp-based fungible token with transfer routing & whitelist
23
+ │ ├── KAP-721/ Non-fungible token standard (ERC-721-like), enumerable + metadata
24
+ │ └── KAP-1155/ Multi-token standard (ERC-1155-like), enumerable + metadata
25
+ ├── access/ Ownable, Committee, Authorization(KAP), AccessController(KAP)
26
+ ├── kyc/ KYCHandler — KYC level enforcement against the KUB KYC registry
27
+ ├── utils/ Pausable, Context, KAP-165 introspection
28
+ ├── libs/ Address, String, EnumerableSet (uint/address), EnumerableMap
29
+ └── interfaces/ IAdminProjectRouter, IKYCBitkubChain
30
+ ```
31
+
32
+ ### Token standards
33
+
34
+ | Standard | Type | Description |
35
+ | --- | --- | --- |
36
+ | **KAP-20** | Fungible | ERC-20-style token integrated with KYC, the admin project router, committee control, and a transfer router. |
37
+ | **KAP-22** | Fungible | Period-based ("stamp") token tracking balances per period, with a transfer router and address whitelist. |
38
+ | **KAP-721** | Non-fungible | ERC-721-style NFT with enumerable and metadata extensions. |
39
+ | **KAP-1155** | Multi-token | ERC-1155-style token with enumerable and metadata extensions. |
40
+
41
+ ### Access & KYC
42
+
43
+ - **Ownable / Committee** — single-owner and committee-governed roles.
44
+ - **Authorization / AuthorizationKAP** — permissioning via an `AdminProjectRouter`.
45
+ - **AccessController / AccessControllerKAP** — compose Ownable, Committee, Authorization, and KYCHandler, adding helpers such as `onlyOwnerOrCommittee` and transfer-router management.
46
+ - **KYCHandler** — stores the accepted KYC level and toggles whether only KYC-verified addresses may interact, validating against `IKYCBitkubChain`.
47
+
48
+ ## Usage
49
+
50
+ These are abstract base contracts intended to be inherited and configured by your concrete token. For example, a KAP-20 token is constructed with its name, symbol, project name, decimals, and the addresses of the KYC registry, admin project router, committee, and transfer router, along with the accepted KYC level:
51
+
52
+ ```solidity
53
+ // SPDX-License-Identifier: MIT
54
+ pragma solidity ^0.8.0;
55
+
56
+ import {KAP20} from "./contracts/token/KAP-20/KAP20.sol";
57
+
58
+ contract MyToken is KAP20 {
59
+ constructor(
60
+ address kyc,
61
+ address adminProjectRouter,
62
+ address committee,
63
+ address transferRouter
64
+ )
65
+ KAP20(
66
+ "My Token", // name
67
+ "MTK", // symbol
68
+ "my-project", // project name
69
+ 18, // decimals
70
+ kyc,
71
+ adminProjectRouter,
72
+ committee,
73
+ transferRouter,
74
+ 4 // accepted KYC level
75
+ )
76
+ {}
77
+ }
78
+ ```
79
+
80
+ Use the contracts as provided rather than copying and modifying them, so deployments stay consistent with the KAP standards and KUB's KYC and admin-routing requirements. For more information, visit [KUB Docs](https://docs.kubchain.com).
81
+
82
+ ## Security
83
+
84
+ These contracts integrate with privileged roles (owner, committee, admin project router) and an external KYC registry. Configure those addresses carefully, and review the access-control wiring before deploying to mainnet. Using this code is not a substitute for an independent security audit.
85
+
86
+ ## License
87
+
88
+ Released under the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,96 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ import {Authorization, IAdminProjectRouter} from "./Authorization.sol";
6
+ import {IKYCBitkubChain} from "../interfaces/IKYCBitkubChain.sol";
7
+ import {KYCHandler} from "../kyc/KYCHandler.sol";
8
+ import {Ownable} from "./Ownable.sol";
9
+ import {Committee} from "./Committee.sol";
10
+
11
+ abstract contract AccessController is
12
+ Authorization,
13
+ KYCHandler,
14
+ Ownable,
15
+ Committee
16
+ {
17
+ event TransferRouterSet(
18
+ address indexed oldTransferRouter,
19
+ address indexed newTransferRouter,
20
+ address indexed caller
21
+ );
22
+
23
+ address public transferRouter;
24
+
25
+ modifier onlyOwnerOrCommittee() {
26
+ require(
27
+ msg.sender == owner() || msg.sender == committee,
28
+ "AccessController: restricted only owner or committee"
29
+ );
30
+ _;
31
+ }
32
+
33
+ modifier onlySuperAdminOrTransferRouter() {
34
+ require(
35
+ adminProjectRouter.isSuperAdmin(msg.sender, PROJECT) ||
36
+ msg.sender == transferRouter,
37
+ "AccessController: restricted only super admin or transfer router"
38
+ );
39
+ _;
40
+ }
41
+
42
+ modifier onlySuperAdminOrCommittee() {
43
+ require(
44
+ adminProjectRouter.isSuperAdmin(msg.sender, PROJECT) ||
45
+ msg.sender == committee,
46
+ "AccessController: restricted only super admin or committee"
47
+ );
48
+ _;
49
+ }
50
+
51
+ modifier onlySuperAdminOrOwner() {
52
+ require(
53
+ adminProjectRouter.isSuperAdmin(msg.sender, PROJECT) ||
54
+ msg.sender == owner(),
55
+ "AccessController: restricted only super admin or owner"
56
+ );
57
+ _;
58
+ }
59
+
60
+ function activateOnlyKYCAddress() external onlyCommittee {
61
+ _activateOnlyKYCAddress();
62
+ }
63
+
64
+ function setKYC(address _kyc) external onlyCommittee {
65
+ _setKYC(IKYCBitkubChain(_kyc));
66
+ }
67
+
68
+ function setAcceptedKYCLevel(uint256 _kycLevel) external onlyCommittee {
69
+ _setAcceptedKYCLevel(_kycLevel);
70
+ }
71
+
72
+ function setTransferRouter(address _transferRouter)
73
+ external
74
+ onlyOwnerOrCommittee
75
+ {
76
+ emit TransferRouterSet(transferRouter, _transferRouter, msg.sender);
77
+ transferRouter = _transferRouter;
78
+ }
79
+
80
+ function setAdminProjectRouter(address _adminProjectRouter)
81
+ public
82
+ override
83
+ onlyOwnerOrCommittee
84
+ {
85
+ require(
86
+ _adminProjectRouter != address(0),
87
+ "Authorization: new admin project router is the zero address"
88
+ );
89
+ emit AdminProjectRouterSet(
90
+ address(adminProjectRouter),
91
+ _adminProjectRouter,
92
+ msg.sender
93
+ );
94
+ adminProjectRouter = IAdminProjectRouter(_adminProjectRouter);
95
+ }
96
+ }
@@ -0,0 +1,116 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity >=0.8.0;
3
+
4
+ import {WhitelistAddress} from "../token/KAP-22/utils/WhitelistAddress.sol";
5
+ import {TransferRouter} from "../token/KAP-22/utils/TransferRouter.sol";
6
+ // import {KYCHandler} from "../kyc/KYCHandler.sol";
7
+ // import {IKYCBitkubChain} from "../interfaces/IKYCBitkubChain.sol";
8
+
9
+ interface IKYCBitkubChain {
10
+ function kycsLevel(address _addr) external view returns (uint256);
11
+ }
12
+
13
+ abstract contract KYCHandler {
14
+ event OnlyKYCAddressActivated(address indexed caller);
15
+ event KYCSet(
16
+ address indexed oldKYC,
17
+ address indexed newKYC,
18
+ address indexed caller
19
+ );
20
+ event AcceptedKYCLevelSet(
21
+ uint256 indexed oldAcceptedKYCLevelSet,
22
+ uint256 indexed newAcceptedKYCLevelSet,
23
+ address indexed caller
24
+ );
25
+
26
+ IKYCBitkubChain public kyc;
27
+
28
+ uint256 public acceptedKycLevel;
29
+ bool public isActivatedOnlyKycAddress;
30
+
31
+ modifier onlyBitkubNext(address bitkubNext_) {
32
+ _onlyBitkubNext(bitkubNext_);
33
+ _;
34
+ }
35
+
36
+ constructor(address kyc_, uint256 acceptedKycLevel_) {
37
+ _setKyc(IKYCBitkubChain(kyc_));
38
+ _setAcceptedKycLevel(acceptedKycLevel_);
39
+ }
40
+
41
+ function _activateOnlyKycAddress() internal virtual {
42
+ isActivatedOnlyKycAddress = true;
43
+ emit OnlyKYCAddressActivated(msg.sender);
44
+ }
45
+
46
+ function _setKyc(IKYCBitkubChain _kyc) internal virtual {
47
+ emit KYCSet(address(kyc), address(_kyc), msg.sender);
48
+ kyc = _kyc;
49
+ }
50
+
51
+ function _setAcceptedKycLevel(uint256 _kycLevel) internal virtual {
52
+ emit AcceptedKYCLevelSet(acceptedKycLevel, _kycLevel, msg.sender);
53
+ acceptedKycLevel = _kycLevel;
54
+ }
55
+
56
+ function _onlyBitkubNext(address bitkubNext_) internal view {
57
+ require(
58
+ _isBitkubNext(bitkubNext_),
59
+ "KYCHandler: only Bitkub NEXT user"
60
+ );
61
+ }
62
+
63
+ function _isBitkubNext(address bitkubNext_) internal view returns (bool) {
64
+ return kyc.kycsLevel(bitkubNext_) >= acceptedKycLevel;
65
+ }
66
+ }
67
+
68
+
69
+ abstract contract AccessControllerKAP is WhitelistAddress, TransferRouter, KYCHandler {
70
+ address public owner;
71
+
72
+ event OwnerSet(address indexed oldOwner, address indexed newOwner, address indexed caller);
73
+
74
+ modifier onlyOwner() {
75
+ require(msg.sender == owner, "AccessControllerKAP: restricted only owner");
76
+ _;
77
+ }
78
+
79
+ constructor(
80
+ address owner_,
81
+ address transferRouter_,
82
+ address kyc_,
83
+ uint256 acceptedKycLevel_
84
+ ) TransferRouter(transferRouter_) KYCHandler(kyc_, acceptedKycLevel_) {
85
+ owner = owner_;
86
+ }
87
+
88
+ function setTransferRouter(address _transferRouter) public virtual {
89
+ _setTransferRouter(_transferRouter);
90
+ }
91
+
92
+ function setKyc(IKYCBitkubChain _kyc) public virtual {
93
+ _setKyc(_kyc);
94
+ }
95
+
96
+ function setAcceptedKycLevel(uint256 _kycLevel) public virtual {
97
+ _setAcceptedKycLevel(_kycLevel);
98
+ }
99
+
100
+ function activateOnlyKycAddress() public virtual {
101
+ _activateOnlyKycAddress();
102
+ }
103
+
104
+ function setOwner(address _owner) public virtual onlyOwner {
105
+ emit OwnerSet(owner, _owner, msg.sender);
106
+ owner = _owner;
107
+ }
108
+
109
+ function addWhitelistAddress(address _addr) public virtual override onlyOwner {
110
+ WhitelistAddress.addWhitelistAddress(_addr);
111
+ }
112
+
113
+ function revokeWhitelistAddress(address _addr) public virtual override onlyOwner {
114
+ WhitelistAddress.revokeWhitelistAddress(_addr);
115
+ }
116
+ }
@@ -0,0 +1,36 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ import "../interfaces/IAdminProjectRouter.sol";
6
+
7
+ abstract contract Authorization {
8
+ IAdminProjectRouter public adminProjectRouter;
9
+ string public PROJECT;
10
+
11
+ event AdminProjectRouterSet(address indexed oldAdmin, address indexed newAdmin, address indexed caller);
12
+
13
+ modifier onlySuperAdmin() {
14
+ require(adminProjectRouter.isSuperAdmin(msg.sender, PROJECT), "Authorization: restricted only super admin");
15
+ _;
16
+ }
17
+
18
+ modifier onlyAdmin() {
19
+ require(adminProjectRouter.isAdmin(msg.sender, PROJECT), "Authorization: restricted only admin");
20
+ _;
21
+ }
22
+
23
+ modifier onlySuperAdminOrAdmin() {
24
+ require(
25
+ adminProjectRouter.isSuperAdmin(msg.sender, PROJECT) || adminProjectRouter.isAdmin(msg.sender, PROJECT),
26
+ "Authorization: restricted only super admin or admin"
27
+ );
28
+ _;
29
+ }
30
+
31
+ function setAdminProjectRouter(address _adminProjectRouter) public virtual onlySuperAdmin {
32
+ require(_adminProjectRouter != address(0), "Authorization: new admin project router is the zero address");
33
+ emit AdminProjectRouterSet(address(adminProjectRouter), _adminProjectRouter, msg.sender);
34
+ adminProjectRouter = IAdminProjectRouter(_adminProjectRouter);
35
+ }
36
+ }
@@ -0,0 +1,60 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {IAdminProjectRouter} from "../interfaces/IAdminProjectRouter.sol";
5
+
6
+ abstract contract AuthorizationKAP {
7
+ IAdminProjectRouter public adminRouter;
8
+ string public constant PROJECT = "kap-token";
9
+ address public transferRouter;
10
+
11
+ address public committee;
12
+
13
+ event SetAdmin(address indexed oldAdmin, address indexed newAdmin, address indexed caller);
14
+ event SetCommittee(address indexed oldCommittee, address indexed newCommittee, address indexed caller);
15
+
16
+ modifier onlySuperAdmin() {
17
+ require(adminRouter.isSuperAdmin(msg.sender, PROJECT), "Restricted only super admin");
18
+ _;
19
+ }
20
+
21
+ modifier onlyAdmin() {
22
+ require(adminRouter.isAdmin(msg.sender, PROJECT), "Restricted only admin");
23
+ _;
24
+ }
25
+
26
+ modifier onlySuperAdminOrAdmin() {
27
+ require(
28
+ adminRouter.isSuperAdmin(msg.sender, PROJECT) || adminRouter.isAdmin(msg.sender, PROJECT),
29
+ "Restricted only super admin or admin"
30
+ );
31
+ _;
32
+ }
33
+
34
+ modifier onlySuperAdminOrTransferRouter() {
35
+ require(
36
+ adminRouter.isSuperAdmin(msg.sender, PROJECT) || msg.sender == transferRouter,
37
+ "Restricted only super admin ot transfer router"
38
+ );
39
+ _;
40
+ }
41
+
42
+ modifier onlyCommittee() {
43
+ require(msg.sender == committee, "Restricted only committee");
44
+ _;
45
+ }
46
+
47
+ function setAdmin(address _adminRouter) external onlySuperAdmin {
48
+ emit SetAdmin(address(adminRouter), _adminRouter, msg.sender);
49
+ adminRouter = IAdminProjectRouter(_adminRouter);
50
+ }
51
+
52
+ function setCommittee(address _committee) external onlyCommittee {
53
+ emit SetCommittee(committee, _committee, msg.sender);
54
+ committee = _committee;
55
+ }
56
+
57
+ function setTransferRouter(address _transferRouter) external onlySuperAdmin {
58
+ transferRouter = _transferRouter;
59
+ }
60
+ }
@@ -0,0 +1,26 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ abstract contract Committee {
6
+ address public committee;
7
+
8
+ event CommitteeSet(
9
+ address indexed oldCommittee,
10
+ address indexed newCommittee,
11
+ address indexed caller
12
+ );
13
+
14
+ modifier onlyCommittee() {
15
+ require(
16
+ msg.sender == committee,
17
+ "Committee: restricted only committee"
18
+ );
19
+ _;
20
+ }
21
+
22
+ function setCommittee(address _committee) public virtual onlyCommittee {
23
+ emit CommitteeSet(committee, _committee, msg.sender);
24
+ committee = _committee;
25
+ }
26
+ }
@@ -0,0 +1,39 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ import "../utils/Context.sol";
6
+
7
+ abstract contract Ownable is Context {
8
+ address private _owner;
9
+
10
+ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
11
+
12
+ constructor() {
13
+ _transferOwnership(_msgSender());
14
+ }
15
+
16
+ function owner() public view virtual returns (address) {
17
+ return _owner;
18
+ }
19
+
20
+ modifier onlyOwner() {
21
+ require(owner() == _msgSender(), "Ownable: caller is not the owner");
22
+ _;
23
+ }
24
+
25
+ function renounceOwnership() public virtual onlyOwner {
26
+ _transferOwnership(address(0));
27
+ }
28
+
29
+ function transferOwnership(address newOwner) public virtual onlyOwner {
30
+ require(newOwner != address(0), "Ownable: new owner is the zero address");
31
+ _transferOwnership(newOwner);
32
+ }
33
+
34
+ function _transferOwnership(address newOwner) internal virtual {
35
+ address oldOwner = _owner;
36
+ _owner = newOwner;
37
+ emit OwnershipTransferred(oldOwner, newOwner);
38
+ }
39
+ }
@@ -0,0 +1,9 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.6.0 <0.9.0;
4
+
5
+ interface IAdminProjectRouter {
6
+ function isSuperAdmin(address _addr, string calldata _project) external view returns (bool);
7
+
8
+ function isAdmin(address _addr, string calldata _project) external view returns (bool);
9
+ }
@@ -0,0 +1,8 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ interface IKYCBitkubChain {
5
+ function kycsLevel(address _addr) external view returns (uint256);
6
+
7
+ function setKycCompleted(address _addr, uint256 _level) external;
8
+ }
@@ -0,0 +1,24 @@
1
+ //SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ import {IKYCBitkubChain} from "../interfaces/IKYCBitkubChain.sol";
6
+
7
+ abstract contract KYCHandler {
8
+ IKYCBitkubChain public kyc;
9
+
10
+ uint256 public acceptedKYCLevel;
11
+ bool public isActivatedOnlyKYCAddress;
12
+
13
+ function _activateOnlyKYCAddress() internal virtual {
14
+ isActivatedOnlyKYCAddress = true;
15
+ }
16
+
17
+ function _setKYC(IKYCBitkubChain _kyc) internal virtual {
18
+ kyc = _kyc;
19
+ }
20
+
21
+ function _setAcceptedKYCLevel(uint256 _kycLevel) internal virtual {
22
+ acceptedKYCLevel = _kycLevel;
23
+ }
24
+ }
@@ -0,0 +1,16 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ library Address {
5
+ function isContract(address account) internal view returns (bool) {
6
+ // This method relies on extcodesize, which returns 0 for contracts in
7
+ // construction, since the code is only stored at the end of the
8
+ // constructor execution.
9
+
10
+ uint256 size;
11
+ assembly {
12
+ size := extcodesize(account)
13
+ }
14
+ return size > 0;
15
+ }
16
+ }
@@ -0,0 +1,70 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ library EnumerableSetAddress {
5
+ struct AddressSet {
6
+ address[] _values;
7
+ mapping(address => uint256) _indexes;
8
+ }
9
+
10
+ function add(AddressSet storage set, address value) internal returns (bool) {
11
+ if (!contains(set, value)) {
12
+ set._values.push(value);
13
+ set._indexes[value] = set._values.length;
14
+ return true;
15
+ } else {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ function remove(AddressSet storage set, address value) internal returns (bool) {
21
+ uint256 valueIndex = set._indexes[value];
22
+ if (valueIndex != 0) {
23
+ uint256 toDeleteIndex = valueIndex - 1;
24
+ uint256 lastIndex = set._values.length - 1;
25
+ address lastvalue = set._values[lastIndex];
26
+ set._values[toDeleteIndex] = lastvalue;
27
+ set._indexes[lastvalue] = toDeleteIndex + 1;
28
+ set._values.pop();
29
+ delete set._indexes[value];
30
+ return true;
31
+ } else {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ function contains(AddressSet storage set, address value) internal view returns (bool) {
37
+ return set._indexes[value] != 0;
38
+ }
39
+
40
+ function length(AddressSet storage set) internal view returns (uint256) {
41
+ return set._values.length;
42
+ }
43
+
44
+ function at(AddressSet storage set, uint256 index) internal view returns (address) {
45
+ require(set._values.length > index, "EnumerableSet: index out of bounds");
46
+ return set._values[index];
47
+ }
48
+
49
+ function getAll(AddressSet storage set) internal view returns (address[] memory) {
50
+ return set._values;
51
+ }
52
+
53
+ function get(AddressSet storage set, uint256 _page, uint256 _limit) internal view returns (address[] memory) {
54
+ require(_page > 0 && _limit > 0);
55
+ uint256 tempLength = _limit;
56
+ uint256 cursor = (_page - 1) * _limit;
57
+ uint256 _addressLength = length(set);
58
+ if (cursor >= _addressLength) {
59
+ return new address[](0);
60
+ }
61
+ if (tempLength > _addressLength - cursor) {
62
+ tempLength = _addressLength - cursor;
63
+ }
64
+ address[] memory addresses = new address[](tempLength);
65
+ for (uint256 i = 0; i < tempLength; i++) {
66
+ addresses[i] = at(set, cursor + i);
67
+ }
68
+ return addresses;
69
+ }
70
+ }
@@ -0,0 +1,74 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity >=0.6.0;
3
+
4
+ library EnumerableSetUint {
5
+ struct UintSet {
6
+ uint256[] _values;
7
+ mapping(uint256 => uint256) _indexes;
8
+ }
9
+
10
+ function add(UintSet storage set, uint256 value) internal returns (bool) {
11
+ if (!contains(set, value)) {
12
+ set._values.push(value);
13
+ set._indexes[value] = set._values.length;
14
+ return true;
15
+ } else {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ function remove(UintSet storage set, uint256 value) internal returns (bool) {
21
+ uint256 valueIndex = set._indexes[value];
22
+ if (valueIndex != 0) {
23
+ uint256 toDeleteIndex = valueIndex - 1;
24
+ uint256 lastIndex = set._values.length - 1;
25
+ uint256 lastvalue = set._values[lastIndex];
26
+ set._values[toDeleteIndex] = lastvalue;
27
+ set._indexes[lastvalue] = toDeleteIndex + 1;
28
+ set._values.pop();
29
+ delete set._indexes[value];
30
+ return true;
31
+ } else {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ function contains(UintSet storage set, uint256 value) internal view returns (bool) {
37
+ return set._indexes[value] != 0;
38
+ }
39
+
40
+ function length(UintSet storage set) internal view returns (uint256) {
41
+ return set._values.length;
42
+ }
43
+
44
+ function at(UintSet storage set, uint256 index) internal view returns (uint256) {
45
+ require(set._values.length > index, "EnumerableSet: index out of bounds");
46
+ return set._values[index];
47
+ }
48
+
49
+ function getAll(UintSet storage set) internal view returns (uint256[] memory) {
50
+ return set._values;
51
+ }
52
+
53
+ function get(
54
+ UintSet storage set,
55
+ uint256 _page,
56
+ uint256 _limit
57
+ ) internal view returns (uint256[] memory) {
58
+ require(_page > 0 && _limit > 0);
59
+ uint256 tempLength = _limit;
60
+ uint256 cursor = (_page - 1) * _limit;
61
+ uint256 _uintLength = length(set);
62
+ if (cursor >= _uintLength) {
63
+ return new uint256[](0);
64
+ }
65
+ if (tempLength > _uintLength - cursor) {
66
+ tempLength = _uintLength - cursor;
67
+ }
68
+ uint256[] memory uintList = new uint256[](tempLength);
69
+ for (uint256 i = 0; i < tempLength; i++) {
70
+ uintList[i] = at(set, cursor + i);
71
+ }
72
+ return uintList;
73
+ }
74
+ }