11pragma solidity  ^ 0.5.0 ;
22
3+ import  "../interfaces/IDataStore.sol " ;
34import  "openzeppelin-solidity/contracts/math/SafeMath.sol " ;
45import  "../storage/modules/TransferManager/VolumeRestrictionTMStorage.sol " ;
56
67library  VolumeRestrictionLib  {
78
89    using SafeMath   for  uint256 ;
910
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+ 
1017    function _checkLengthOfArray  (
1118        address [] memory  _holders ,
1219        uint256 [] memory  _allowedTokens ,
@@ -28,60 +35,89 @@ library VolumeRestrictionLib {
2835        );
2936    }
3037
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+     {
3246        // Deleting the holder if holder's type of Period is `Both` type otherwise 
3347        // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod 
3448        // `_typeOfPeriod` it always be contrary to the removing restriction 
3549        // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay 
3650        // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod 
3751        // 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);
4757        } else  {
48-             data.restrictedHolders [_holder].typeOfPeriod  =  _typeOfPeriod;
58+             holderToRestrictionType [_holder] =  _typeOfPeriod;
4959        }
5060    }
5161
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 ));
5778        }
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;
6085    }
6186
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-     }
6887
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+      */ 
6998    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+             )
80113    {
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+             }
85121        }
86122        allAddresses =  new  address [](counter);
87123        allowedTokens =  new  uint256 [](counter);
@@ -90,21 +126,23 @@ library VolumeRestrictionLib {
90126        endTime =  new  uint256 [](counter);
91127        typeOfRestriction =  new  uint8 [](counter);
92128        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+                 }
103144                counter++ ;
104-                 allAddresses[counter] =   _holderData.restrictedAddresses[i];
105-                 _setValues (_individualRestrictions.individualDailyRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter);
106145            }
107-             counter++ ;
108146        }
109147    }
110148
@@ -127,4 +165,26 @@ library VolumeRestrictionLib {
127165        typeOfRestriction[index] =  uint8 (restriction.typeOfRestriction);
128166    }
129167
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+ 
130190}
0 commit comments