Skip to content

Commit 0008f28

Browse files
maxsam4adamdossa
authored andcommitted
gtm matm optimizations (#601)
* MATM optimizations * Added code comments * Updated tests * Updated names * Added overflow check
1 parent 3d45fb2 commit 0008f28

File tree

4 files changed

+161
-143
lines changed

4 files changed

+161
-143
lines changed

contracts/modules/TransferManager/GeneralTransferManager.sol

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
2424
// Emit when there is change in the flag variable called signingAddress
2525
event ChangeSigningAddress(address _signingAddress);
2626
// Emit when investor details get modified related to their whitelisting
27-
event ChangeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime);
27+
event ChangeDefaults(uint64 _defaultCanSendAfter, uint64 _defaultCanReceiveAfter);
2828

29-
// _fromTime is the time from which the _investor can send tokens
30-
// _toTime is the time from which the _investor can receive tokens
31-
// if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address
32-
// if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens
29+
// _canSendAfter is the time from which the _investor can send tokens
30+
// _canReceiveAfter is the time from which the _investor can receive tokens
31+
// if allowAllWhitelistIssuances is TRUE, then _canReceiveAfter is ignored when receiving tokens from the issuance address
32+
// if allowAllWhitelistTransfers is TRUE, then _canReceiveAfter and _canSendAfter is ignored when sending or receiving tokens
3333
// in any case, any investor sending or receiving tokens, must have a _expiryTime in the future
3434
event ModifyWhitelist(
3535
address indexed _investor,
3636
uint256 _dateAdded,
3737
address indexed _addedBy,
38-
uint256 _fromTime,
39-
uint256 _toTime,
38+
uint256 _canSendAfter,
39+
uint256 _canReceiveAfter,
4040
uint256 _expiryTime,
4141
bool _canBuyFromSTO
4242
);
@@ -60,21 +60,25 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
6060
}
6161

6262
/**
63-
* @notice Used to change the default times used when fromTime / toTime are zero
64-
* @param _defaultFromTime default for zero fromTime
65-
* @param _defaultToTime default for zero toTime
63+
* @notice Used to change the default times used when canSendAfter / canReceiveAfter are zero
64+
* @param _defaultCanSendAfter default for zero canSendAfter
65+
* @param _defaultCanReceiveAfter default for zero canReceiveAfter
6666
*/
67-
function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) {
68-
defaults.fromTime = _defaultFromTime;
69-
defaults.toTime = _defaultToTime;
70-
emit ChangeDefaults(_defaultFromTime, _defaultToTime);
67+
function changeDefaults(uint64 _defaultCanSendAfter, uint64 _defaultCanReceiveAfter) public withPerm(FLAGS) {
68+
/* 0 values are also allowed as they represent that the Issuer
69+
does not want a default value for these variables.
70+
0 is also the default value of these variables */
71+
defaults.canSendAfter = _defaultCanSendAfter;
72+
defaults.canReceiveAfter = _defaultCanReceiveAfter;
73+
emit ChangeDefaults(_defaultCanSendAfter, _defaultCanReceiveAfter);
7174
}
7275

7376
/**
7477
* @notice Used to change the Issuance Address
7578
* @param _issuanceAddress new address for the issuance
7679
*/
7780
function changeIssuanceAddress(address _issuanceAddress) public withPerm(FLAGS) {
81+
// address(0x0) is also a valid value and in most cases, the address that issues tokens is 0x0.
7882
issuanceAddress = _issuanceAddress;
7983
emit ChangeIssuanceAddress(_issuanceAddress);
8084
}
@@ -84,6 +88,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
8488
* @param _signingAddress new address for the signing
8589
*/
8690
function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) {
91+
/* address(0x0) is also a valid value as an Issuer might want to
92+
give this permission to nobody (except their own address).
93+
0x0 is also the default value */
8794
signingAddress = _signingAddress;
8895
emit ChangeSigningAddress(_signingAddress);
8996
}
@@ -156,7 +163,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
156163
return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA;
157164
}
158165

159-
(uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime);
166+
(uint64 adjustedCanSendAfter, uint64 adjustedCanReceiveAfter) = _adjustTimes(whitelist[_from].canSendAfter, whitelist[_to].canReceiveAfter);
160167
if (_from == issuanceAddress) {
161168
// Possible STO transaction, but investor not allowed to purchased from STO
162169
if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) {
@@ -166,51 +173,51 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
166173
if (allowAllWhitelistIssuances) {
167174
return _onWhitelist(_to) ? Result.VALID : Result.NA;
168175
} else {
169-
return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA;
176+
return (_onWhitelist(_to) && (adjustedCanReceiveAfter <= uint64(now))) ? Result.VALID : Result.NA;
170177
}
171178
}
172179

173180
//Anyone on the whitelist can transfer provided the blocknumber is large enough
174181
/*solium-disable-next-line security/no-block-members*/
175-
return ((_onWhitelist(_from) && (adjustedFromTime <= uint64(now))) &&
176-
(_onWhitelist(_to) && (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/
182+
return ((_onWhitelist(_from) && (adjustedCanSendAfter <= uint64(now))) &&
183+
(_onWhitelist(_to) && (adjustedCanReceiveAfter <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/
177184
}
178185
return Result.NA;
179186
}
180187

181188
/**
182189
* @notice Adds or removes addresses from the whitelist.
183190
* @param _investor is the address to whitelist
184-
* @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens
185-
* @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
191+
* @param _canSendAfter the moment when the sale lockup period ends and the investor can freely sell or transfer away their tokens
192+
* @param _canReceiveAfter the moment when the purchase lockup period ends and the investor can freely purchase or receive from others
186193
* @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC
187194
* @param _canBuyFromSTO is used to know whether the investor is restricted investor or not.
188195
*/
189196
function modifyWhitelist(
190197
address _investor,
191-
uint256 _fromTime,
192-
uint256 _toTime,
198+
uint256 _canSendAfter,
199+
uint256 _canReceiveAfter,
193200
uint256 _expiryTime,
194201
bool _canBuyFromSTO
195202
)
196203
public
197204
withPerm(WHITELIST)
198205
{
199-
_modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO);
206+
_modifyWhitelist(_investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO);
200207
}
201208

202209
/**
203210
* @notice Adds or removes addresses from the whitelist.
204211
* @param _investor is the address to whitelist
205-
* @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens
206-
* @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
212+
* @param _canSendAfter is the moment when the sale lockup period ends and the investor can freely sell his tokens
213+
* @param _canReceiveAfter is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
207214
* @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC
208215
* @param _canBuyFromSTO is used to know whether the investor is restricted investor or not.
209216
*/
210217
function _modifyWhitelist(
211218
address _investor,
212-
uint256 _fromTime,
213-
uint256 _toTime,
219+
uint256 _canSendAfter,
220+
uint256 _canReceiveAfter,
214221
uint256 _expiryTime,
215222
bool _canBuyFromSTO
216223
)
@@ -224,39 +231,45 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
224231
if (whitelist[_investor].added == uint8(0)) {
225232
investors.push(_investor);
226233
}
227-
whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1));
228-
emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO);
234+
require(
235+
uint64(_canSendAfter) == _canSendAfter &&
236+
uint64(_canReceiveAfter) == _canReceiveAfter &&
237+
uint64(_expiryTime) == _expiryTime,
238+
"uint64 overflow"
239+
);
240+
whitelist[_investor] = TimeRestriction(uint64(_canSendAfter), uint64(_canReceiveAfter), uint64(_expiryTime), canBuyFromSTO, uint8(1));
241+
emit ModifyWhitelist(_investor, now, msg.sender, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO);
229242
}
230243

231244
/**
232245
* @notice Adds or removes addresses from the whitelist.
233246
* @param _investors List of the addresses to whitelist
234-
* @param _fromTimes An array of the moment when the sale lockup period ends and the investor can freely sell his tokens
235-
* @param _toTimes An array of the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
247+
* @param _canSendAfters An array of the moment when the sale lockup period ends and the investor can freely sell his tokens
248+
* @param _canReceiveAfters An array of the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
236249
* @param _expiryTimes An array of the moment till investors KYC will be validated. After that investor need to do re-KYC
237250
* @param _canBuyFromSTO An array of boolean values
238251
*/
239252
function modifyWhitelistMulti(
240253
address[] _investors,
241-
uint256[] _fromTimes,
242-
uint256[] _toTimes,
254+
uint256[] _canSendAfters,
255+
uint256[] _canReceiveAfters,
243256
uint256[] _expiryTimes,
244257
bool[] _canBuyFromSTO
245258
) public withPerm(WHITELIST) {
246-
require(_investors.length == _fromTimes.length, "Mismatched input lengths");
247-
require(_fromTimes.length == _toTimes.length, "Mismatched input lengths");
248-
require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths");
249-
require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length");
259+
require(_investors.length == _canSendAfters.length, "Mismatched input lengths");
260+
require(_canSendAfters.length == _canReceiveAfters.length, "Mismatched input lengths");
261+
require(_canReceiveAfters.length == _expiryTimes.length, "Mismatched input lengths");
262+
require(_canBuyFromSTO.length == _canReceiveAfters.length, "Mismatched input length");
250263
for (uint256 i = 0; i < _investors.length; i++) {
251-
_modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]);
264+
_modifyWhitelist(_investors[i], _canSendAfters[i], _canReceiveAfters[i], _expiryTimes[i], _canBuyFromSTO[i]);
252265
}
253266
}
254267

255268
/**
256269
* @notice Adds or removes addresses from the whitelist - can be called by anyone with a valid signature
257270
* @param _investor is the address to whitelist
258-
* @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens
259-
* @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
271+
* @param _canSendAfter is the moment when the sale lockup period ends and the investor can freely sell his tokens
272+
* @param _canReceiveAfter is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
260273
* @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC
261274
* @param _canBuyFromSTO is used to know whether the investor is restricted investor or not.
262275
* @param _validFrom is the time that this signature is valid from
@@ -268,8 +281,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
268281
*/
269282
function modifyWhitelistSigned(
270283
address _investor,
271-
uint256 _fromTime,
272-
uint256 _toTime,
284+
uint256 _canSendAfter,
285+
uint256 _canReceiveAfter,
273286
uint256 _expiryTime,
274287
bool _canBuyFromSTO,
275288
uint256 _validFrom,
@@ -286,18 +299,18 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
286299
require(!nonceMap[_investor][_nonce], "Already used signature");
287300
nonceMap[_investor][_nonce] = true;
288301
bytes32 hash = keccak256(
289-
abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce)
302+
abi.encodePacked(this, _investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce)
290303
);
291304
_checkSig(hash, _v, _r, _s);
292-
_modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO);
305+
_modifyWhitelist(_investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO);
293306
}
294307

295308
/**
296309
* @notice Used to verify the signature
297310
*/
298311
function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view {
299312
//Check that the signature is valid
300-
//sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address
313+
//sig should be signing - _investor, _canSendAfter, _canReceiveAfter & _expiryTime and be signed by the issuer address
301314
address signer = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), _v, _r, _s);
302315
require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer");
303316
}
@@ -322,16 +335,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
322335
/**
323336
* @notice Internal function to adjust times using default values
324337
*/
325-
function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) {
326-
uint64 adjustedFromTime = _fromTime;
327-
uint64 adjustedToTime = _toTime;
328-
if (_fromTime == 0) {
329-
adjustedFromTime = defaults.fromTime;
338+
function _adjustTimes(uint64 _canSendAfter, uint64 _canReceiveAfter) internal view returns(uint64, uint64) {
339+
uint64 adjustedCanSendAfter = _canSendAfter;
340+
uint64 adjustedCanReceiveAfter = _canReceiveAfter;
341+
if (_canSendAfter == 0) {
342+
adjustedCanSendAfter = defaults.canSendAfter;
330343
}
331-
if (_toTime == 0) {
332-
adjustedToTime = defaults.toTime;
344+
if (_canReceiveAfter == 0) {
345+
adjustedCanReceiveAfter = defaults.canReceiveAfter;
333346
}
334-
return (adjustedFromTime, adjustedToTime);
347+
return (adjustedCanSendAfter, adjustedCanReceiveAfter);
335348
}
336349

337350
/**
@@ -345,9 +358,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
345358
* @dev Returns list of all investors data
346359
*/
347360
function getAllInvestorsData() external view returns(address[], uint256[], uint256[], uint256[], bool[]) {
348-
(uint256[] memory fromTimes, uint256[] memory toTimes, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs)
361+
(uint256[] memory canSendAfters, uint256[] memory canReceiveAfters, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs)
349362
= _investorsData(investors);
350-
return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs);
363+
return (investors, canSendAfters, canReceiveAfters, expiryTimes, canBuyFromSTOs);
351364

352365
}
353366

@@ -359,21 +372,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag
359372
}
360373

361374
function _investorsData(address[] _investors) internal view returns(uint256[], uint256[], uint256[], bool[]) {
362-
uint256[] memory fromTimes = new uint256[](_investors.length);
363-
uint256[] memory toTimes = new uint256[](_investors.length);
375+
uint256[] memory canSendAfters = new uint256[](_investors.length);
376+
uint256[] memory canReceiveAfters = new uint256[](_investors.length);
364377
uint256[] memory expiryTimes = new uint256[](_investors.length);
365378
bool[] memory canBuyFromSTOs = new bool[](_investors.length);
366379
for (uint256 i = 0; i < _investors.length; i++) {
367-
fromTimes[i] = whitelist[_investors[i]].fromTime;
368-
toTimes[i] = whitelist[_investors[i]].toTime;
380+
canSendAfters[i] = whitelist[_investors[i]].canSendAfter;
381+
canReceiveAfters[i] = whitelist[_investors[i]].canReceiveAfter;
369382
expiryTimes[i] = whitelist[_investors[i]].expiryTime;
370383
if (whitelist[_investors[i]].canBuyFromSTO == 0) {
371384
canBuyFromSTOs[i] = false;
372385
} else {
373386
canBuyFromSTOs[i] = true;
374387
}
375388
}
376-
return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs);
389+
return (canSendAfters, canReceiveAfters, expiryTimes, canBuyFromSTOs);
377390
}
378391

379392
/**

0 commit comments

Comments
 (0)