1
1
pragma solidity ^ 0.5.0 ;
2
2
3
+ import "../interfaces/IDataStore.sol " ;
3
4
import "openzeppelin-solidity/contracts/math/SafeMath.sol " ;
4
5
import "../storage/modules/TransferManager/VolumeRestrictionTMStorage.sol " ;
5
6
6
7
library VolumeRestrictionLib {
7
8
8
9
using SafeMath for uint256 ;
9
10
11
+ uint256 internal constant ONE = uint256 (1 );
12
+ uint8 internal constant INDEX = uint8 (2 );
13
+ bytes32 internal constant INVESTORFLAGS = "INVESTORFLAGS " ;
14
+ bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731 ; //keccak256(abi.encodePacked("INVESTORS"))
15
+ bytes32 internal constant WHITELIST = "WHITELIST " ;
16
+
10
17
function _checkLengthOfArray (
11
18
address [] memory _holders ,
12
19
uint256 [] memory _allowedTokens ,
@@ -28,60 +35,89 @@ library VolumeRestrictionLib {
28
35
);
29
36
}
30
37
31
- function deleteHolderFromList (VolumeRestrictionTMStorage.RestrictedData storage data , address _holder , uint8 _typeOfPeriod ) public {
38
+ function deleteHolderFromList (
39
+ mapping (address => uint8 ) storage holderToRestrictionType ,
40
+ address _holder ,
41
+ address _dataStore ,
42
+ uint8 _typeOfPeriod
43
+ )
44
+ public
45
+ {
32
46
// Deleting the holder if holder's type of Period is `Both` type otherwise
33
47
// it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod
34
48
// `_typeOfPeriod` it always be contrary to the removing restriction
35
49
// if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay
36
50
// in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod
37
51
// is TypeOfPeriod.MultipleDays in uint8 its value is 0.
38
- if (data.restrictedHolders[_holder].typeOfPeriod != uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both)) {
39
- uint128 index = data.restrictedHolders[_holder].index;
40
- uint256 _len = data.restrictedAddresses.length ;
41
- if (index != _len) {
42
- data.restrictedHolders[data.restrictedAddresses[_len - 1 ]].index = index;
43
- data.restrictedAddresses[index - 1 ] = data.restrictedAddresses[_len - 1 ];
44
- }
45
- delete data.restrictedHolders[_holder];
46
- data.restrictedAddresses.length -- ;
52
+ if (holderToRestrictionType[_holder] != uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both)) {
53
+ IDataStore dataStore = IDataStore (_dataStore);
54
+ uint256 flags = dataStore.getUint256 (_getKey (INVESTORFLAGS, _holder));
55
+ flags = flags & ~ (ONE << INDEX);
56
+ dataStore.setUint256 (_getKey (INVESTORFLAGS, _holder), flags);
47
57
} else {
48
- data.restrictedHolders [_holder].typeOfPeriod = _typeOfPeriod;
58
+ holderToRestrictionType [_holder] = _typeOfPeriod;
49
59
}
50
60
}
51
61
52
- function addRestrictionData (VolumeRestrictionTMStorage.RestrictedData storage data , address _holder , uint8 _callFrom , uint256 _endTime ) public {
53
- uint128 index = data.restrictedHolders[_holder].index;
54
- if (data.restrictedHolders[_holder].seen == 0 ) {
55
- data.restrictedAddresses.push (_holder);
56
- index = uint128 (data.restrictedAddresses.length );
62
+ function addRestrictionData (
63
+ mapping (address => uint8 ) storage holderToRestrictionType ,
64
+ address _holder ,
65
+ uint8 _callFrom ,
66
+ uint256 _endTime ,
67
+ address _dataStore
68
+ )
69
+ public
70
+ {
71
+ IDataStore dataStore = IDataStore (_dataStore);
72
+
73
+ uint256 flags = dataStore.getUint256 (_getKey (INVESTORFLAGS, _holder));
74
+ if (! _isExistingInvestor (_holder, dataStore)) {
75
+ dataStore.insertAddress (INVESTORSKEY, _holder);
76
+ //KYC data can not be present if added is false and hence we can set packed KYC as uint256(1) to set added as true
77
+ dataStore.setUint256 (_getKey (WHITELIST, _holder), uint256 (1 ));
57
78
}
58
- uint8 _type = _getTypeOfPeriod (data.restrictedHolders[_holder].typeOfPeriod, _callFrom, _endTime);
59
- data.restrictedHolders[_holder] = VolumeRestrictionTMStorage.RestrictedHolder (uint8 (1 ), _type, index);
79
+ if (! _isVolRestricted (flags)) {
80
+ flags = flags | (ONE << INDEX);
81
+ dataStore.setUint256 (_getKey (INVESTORFLAGS, _holder), flags);
82
+ }
83
+ uint8 _type = _getTypeOfPeriod (holderToRestrictionType[_holder], _callFrom, _endTime);
84
+ holderToRestrictionType[_holder] = _type;
60
85
}
61
86
62
- function _getTypeOfPeriod (uint8 _currentTypeOfPeriod , uint8 _callFrom , uint256 _endTime ) internal pure returns (uint8 ) {
63
- if (_currentTypeOfPeriod != _callFrom && _endTime != uint256 (0 ))
64
- return uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both);
65
- else
66
- return _callFrom;
67
- }
68
87
88
+ /**
89
+ * @notice Provide the restriction details of all the restricted addresses
90
+ * @return address List of the restricted addresses
91
+ * @return uint256 List of the tokens allowed to the restricted addresses corresponds to restricted address
92
+ * @return uint256 List of the start time of the restriction corresponds to restricted address
93
+ * @return uint256 List of the rolling period in days for a restriction corresponds to restricted address.
94
+ * @return uint256 List of the end time of the restriction corresponds to restricted address.
95
+ * @return uint8 List of the type of restriction to validate the value of the `allowedTokens`
96
+ * of the restriction corresponds to restricted address
97
+ */
69
98
function getRestrictionData (
70
- VolumeRestrictionTMStorage.RestrictedData storage _holderData ,
71
- VolumeRestrictionTMStorage.IndividualRestrictions storage _individualRestrictions
72
- ) public view returns (
73
- address [] memory allAddresses ,
74
- uint256 [] memory allowedTokens ,
75
- uint256 [] memory startTime ,
76
- uint256 [] memory rollingPeriodInDays ,
77
- uint256 [] memory endTime ,
78
- uint8 [] memory typeOfRestriction
79
- )
99
+ mapping (address => uint8 ) storage holderToRestrictionType ,
100
+ VolumeRestrictionTMStorage.IndividualRestrictions storage _individualRestrictions ,
101
+ address _dataStore
102
+ )
103
+ public
104
+ view
105
+ returns (
106
+ address [] memory allAddresses ,
107
+ uint256 [] memory allowedTokens ,
108
+ uint256 [] memory startTime ,
109
+ uint256 [] memory rollingPeriodInDays ,
110
+ uint256 [] memory endTime ,
111
+ uint8 [] memory typeOfRestriction
112
+ )
80
113
{
81
- uint256 counter = 0 ;
82
- uint256 i = 0 ;
83
- for (i = 0 ; i < _holderData.restrictedAddresses.length ; i++ ) {
84
- counter = counter + (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8 (2 ) ? 2 : 1 );
114
+ address [] memory investors = IDataStore (_dataStore).getAddressArray (INVESTORSKEY);
115
+ uint256 counter;
116
+ uint256 i;
117
+ for (i = 0 ; i < investors.length ; i++ ) {
118
+ if (_isVolRestricted (IDataStore (_dataStore).getUint256 (_getKey (INVESTORFLAGS, investors[i])))) {
119
+ counter = counter + (holderToRestrictionType[investors[i]] == uint8 (2 ) ? 2 : 1 );
120
+ }
85
121
}
86
122
allAddresses = new address [](counter);
87
123
allowedTokens = new uint256 [](counter);
@@ -90,21 +126,23 @@ library VolumeRestrictionLib {
90
126
endTime = new uint256 [](counter);
91
127
typeOfRestriction = new uint8 [](counter);
92
128
counter = 0 ;
93
- for (i = 0 ; i < _holderData.restrictedAddresses.length ; i++ ) {
94
- allAddresses[counter] = _holderData.restrictedAddresses[i];
95
- if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.MultipleDays)) {
96
- _setValues (_individualRestrictions.individualRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
97
- }
98
- else if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.OneDay)) {
99
- _setValues (_individualRestrictions.individualDailyRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
100
- }
101
- else if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both)) {
102
- _setValues (_individualRestrictions.individualRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
129
+ for (i = 0 ; i < investors.length ; i++ ) {
130
+ if (_isVolRestricted (IDataStore (_dataStore).getUint256 (_getKey (INVESTORFLAGS, investors[i])))) {
131
+ allAddresses[counter] = investors[i];
132
+ if (holderToRestrictionType[investors[i]] == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.MultipleDays)) {
133
+ _setValues (_individualRestrictions.individualRestriction[investors[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
134
+ }
135
+ else if (holderToRestrictionType[investors[i]] == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.OneDay)) {
136
+ _setValues (_individualRestrictions.individualDailyRestriction[investors[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
137
+ }
138
+ else if (holderToRestrictionType[investors[i]] == uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both)) {
139
+ _setValues (_individualRestrictions.individualRestriction[investors[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
140
+ counter++ ;
141
+ allAddresses[counter] = investors[i];
142
+ _setValues (_individualRestrictions.individualDailyRestriction[investors[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
143
+ }
103
144
counter++ ;
104
- allAddresses[counter] = _holderData.restrictedAddresses[i];
105
- _setValues (_individualRestrictions.individualDailyRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
106
145
}
107
- counter++ ;
108
146
}
109
147
}
110
148
@@ -127,4 +165,26 @@ library VolumeRestrictionLib {
127
165
typeOfRestriction[index] = uint8 (restriction.typeOfRestriction);
128
166
}
129
167
168
+ function _isVolRestricted (uint256 _flags ) internal pure returns (bool ) {
169
+ uint256 volRestricted = (_flags >> INDEX) & ONE;
170
+ return (volRestricted > 0 ? true : false );
171
+ }
172
+
173
+ function _getTypeOfPeriod (uint8 _currentTypeOfPeriod , uint8 _callFrom , uint256 _endTime ) internal pure returns (uint8 ) {
174
+ if (_currentTypeOfPeriod != _callFrom && _endTime != uint256 (0 ))
175
+ return uint8 (VolumeRestrictionTMStorage.TypeOfPeriod.Both);
176
+ else
177
+ return _callFrom;
178
+ }
179
+
180
+ function _isExistingInvestor (address _investor , IDataStore dataStore ) internal view returns (bool ) {
181
+ uint256 data = dataStore.getUint256 (_getKey (WHITELIST, _investor));
182
+ //extracts `added` from packed `_whitelistData`
183
+ return uint8 (data) == 0 ? false : true ;
184
+ }
185
+
186
+ function _getKey (bytes32 _key1 , address _key2 ) internal pure returns (bytes32 ) {
187
+ return bytes32 (keccak256 (abi.encodePacked (_key1, _key2)));
188
+ }
189
+
130
190
}
0 commit comments