Skip to content

Commit cd83ece

Browse files
authored
Merge pull request #572 from PolymathNetwork/gtm-logic-refactor
GTM logic refactored
2 parents b205061 + 94139b8 commit cd83ece

8 files changed

+221
-178
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ All notable changes to this project will be documented in this file.
2929
* `modifyWhitelist()` function renamed to `modifyKYCData()`.
3030
* Added functions to modify and get flags
3131
* `canBuyFromSto` is now `canNotBuyFromSto` and it is the flag `1`
32+
* GTM logic reworked. Now, instead of flags like allowAllTransfers, there is a matrix of transfer requirements that must be fulfilled based on type of transfer.
3233

3334
## Generalize
3435
* Removed `_polyAddress` parameter from constructors of all modules and module factories.

contracts/modules/TransferManager/GTM/GeneralTransferManager.sol

Lines changed: 117 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage
1616

1717
// Emit when Issuance address get changed
1818
event ChangeIssuanceAddress(address _issuanceAddress);
19-
// Emit when there is change in the flag variable called allowAllTransfers
20-
event AllowAllTransfers(bool _allowAllTransfers);
21-
// Emit when there is change in the flag variable called allowAllWhitelistTransfers
22-
event AllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers);
23-
// Emit when there is change in the flag variable called allowAllWhitelistIssuances
24-
event AllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances);
25-
// Emit when there is change in the flag variable called allowAllBurnTransfers
26-
event AllowAllBurnTransfers(bool _allowAllBurnTransfers);
19+
2720
// Emit when investor details get modified related to their whitelisting
2821
event ChangeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime);
2922

@@ -46,6 +39,14 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage
4639
bool _value
4740
);
4841

42+
event ModifyTransferRequirements(
43+
uint256 indexed _transferType,
44+
bool _fromValidKYC,
45+
bool _toValidKYC,
46+
bool _fromRestricted,
47+
bool _toRestricted
48+
);
49+
4950
/**
5051
* @notice Constructor
5152
* @param _securityToken Address of the security token
@@ -84,50 +85,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage
8485
emit ChangeIssuanceAddress(_issuanceAddress);
8586
}
8687

87-
/**
88-
* @notice Used to change the flag
89-
true - It refers there are no transfer restrictions, for any addresses
90-
false - It refers transfers are restricted for all addresses.
91-
* @param _allowAllTransfers flag value
92-
*/
93-
function changeAllowAllTransfers(bool _allowAllTransfers) public withPerm(ADMIN) {
94-
allowAllTransfers = _allowAllTransfers;
95-
emit AllowAllTransfers(_allowAllTransfers);
96-
}
97-
98-
/**
99-
* @notice Used to change the flag
100-
true - It refers that time lock is ignored for transfers (address must still be on whitelist)
101-
false - It refers transfers are restricted for all addresses.
102-
* @param _allowAllWhitelistTransfers flag value
103-
*/
104-
function changeAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers) public withPerm(ADMIN) {
105-
allowAllWhitelistTransfers = _allowAllWhitelistTransfers;
106-
emit AllowAllWhitelistTransfers(_allowAllWhitelistTransfers);
107-
}
108-
109-
/**
110-
* @notice Used to change the flag
111-
true - It refers that time lock is ignored for issuances (address must still be on whitelist)
112-
false - It refers transfers are restricted for all addresses.
113-
* @param _allowAllWhitelistIssuances flag value
114-
*/
115-
function changeAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances) public withPerm(ADMIN) {
116-
allowAllWhitelistIssuances = _allowAllWhitelistIssuances;
117-
emit AllowAllWhitelistIssuances(_allowAllWhitelistIssuances);
118-
}
119-
120-
/**
121-
* @notice Used to change the flag
122-
true - It allow to burn the tokens
123-
false - It deactivate the burning mechanism.
124-
* @param _allowAllBurnTransfers flag value
125-
*/
126-
function changeAllowAllBurnTransfers(bool _allowAllBurnTransfers) public withPerm(ADMIN) {
127-
allowAllBurnTransfers = _allowAllBurnTransfers;
128-
emit AllowAllBurnTransfers(_allowAllBurnTransfers);
129-
}
130-
13188
/**
13289
* @notice Default implementation of verifyTransfer used by SecurityToken
13390
* If the transfer request comes from the STO, it only checks that the investor is in the whitelist
@@ -150,67 +107,134 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage
150107

151108
/**
152109
* @notice Default implementation of verifyTransfer used by SecurityToken
153-
* If the transfer request comes from the STO, it only checks that the investor is in the whitelist
154-
* If the transfer request comes from a token holder, it checks that:
155-
* a) Both are on the whitelist
156-
* b) Seller's sale lockup period is over
157-
* c) Buyer's purchase lockup is over
158110
* @param _from Address of the sender
159111
* @param _to Address of the receiver
160112
*/
161113
function verifyTransfer(
162114
address _from,
163115
address _to,
164-
uint256, /*_amount*/
116+
uint256 /*_amount*/,
165117
bytes memory /* _data */
166118
)
167119
public
168120
view
169121
returns(Result, bytes32)
170122
{
171-
Result success;
172123
if (!paused) {
124+
TransferRequirements memory txReq;
173125
uint64 fromTime;
174126
uint64 fromExpiry;
175127
uint64 toExpiry;
176128
uint64 toTime;
177-
if (allowAllTransfers) {
178-
//All transfers allowed, regardless of whitelist
179-
return (Result.VALID, getAddressBytes32());
180-
}
181-
if (allowAllBurnTransfers && (_to == address(0))) {
182-
return (Result.VALID, getAddressBytes32());
129+
130+
if (_from == issuanceAddress) {
131+
txReq = transferRequirements[1]; //Issuance
132+
} else if (_to == address(0)) {
133+
txReq = transferRequirements[2]; //Redemption
134+
} else {
135+
txReq = transferRequirements[0]; //General Transfer
183136
}
184137

185138
(fromTime, fromExpiry, toTime, toExpiry) = _getValuesForTransfer(_from, _to);
186139

187-
if (allowAllWhitelistTransfers) {
188-
//Anyone on the whitelist can transfer, regardless of time
189-
success = (_validExpiry(toExpiry) && _validExpiry(fromExpiry)) ? Result.VALID : Result.NA;
190-
return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0));
140+
if ((txReq.fromValidKYC && !_validExpiry(fromExpiry)) || (txReq.toValidKYC && !_validExpiry(toExpiry))) {
141+
return (Result.NA, bytes32(0));
191142
}
192-
// Using the local variables to avoid the stack too deep error
143+
193144
(fromTime, toTime) = _adjustTimes(fromTime, toTime);
194-
if (_from == issuanceAddress) {
195-
// if allowAllWhitelistIssuances is true, so time stamp ignored
196-
if (allowAllWhitelistIssuances) {
197-
success = _validExpiry(toExpiry) ? Result.VALID : Result.NA;
198-
return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0));
199-
} else {
200-
success = (_validExpiry(toExpiry) && _validLockTime(toTime)) ? Result.VALID : Result.NA;
201-
return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0));
202-
}
145+
146+
if ((txReq.fromRestricted && !_validLockTime(fromTime)) || (txReq.toRestricted && !_validLockTime(toTime))) {
147+
return (Result.NA, bytes32(0));
203148
}
204149

205-
//Anyone on the whitelist can transfer provided the blocknumber is large enough
206-
/*solium-disable-next-line security/no-block-members*/
207-
success = (_validExpiry(fromExpiry) && _validLockTime(fromTime) && _validExpiry(toExpiry) &&
208-
_validLockTime(toTime)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/
209-
return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0));
150+
return (Result.VALID, getAddressBytes32());
210151
}
211152
return (Result.NA, bytes32(0));
212153
}
213154

155+
/**
156+
* @notice Modifies the successful checks required for a transfer to be deemed valid.
157+
* @param _transferType Type of transfer (0 = General, 1 = Issuance, 2 = Redemption)
158+
* @param _fromValidKYC Defines if KYC is required for the sender
159+
* @param _toValidKYC Defines if KYC is required for the receiver
160+
* @param _fromRestricted Defines if transfer time restriction is checked for the sender
161+
* @param _toRestricted Defines if transfer time restriction is checked for the receiver
162+
*/
163+
function modifyTransferRequirements(
164+
uint256 _transferType,
165+
bool _fromValidKYC,
166+
bool _toValidKYC,
167+
bool _fromRestricted,
168+
bool _toRestricted
169+
) public withPerm(ADMIN) {
170+
_modifyTransferRequirements(
171+
_transferType,
172+
_fromValidKYC,
173+
_toValidKYC,
174+
_fromRestricted,
175+
_toRestricted
176+
);
177+
}
178+
179+
/**
180+
* @notice Modifies the successful checks required for transfers.
181+
* @param _transferTypes Types of transfer (0 = General, 1 = Issuance, 2 = Redemption)
182+
* @param _fromValidKYC Defines if KYC is required for the sender
183+
* @param _toValidKYC Defines if KYC is required for the receiver
184+
* @param _fromRestricted Defines if transfer time restriction is checked for the sender
185+
* @param _toRestricted Defines if transfer time restriction is checked for the receiver
186+
*/
187+
function modifyTransferRequirementsMulti(
188+
uint256[] memory _transferTypes,
189+
bool[] memory _fromValidKYC,
190+
bool[] memory _toValidKYC,
191+
bool[] memory _fromRestricted,
192+
bool[] memory _toRestricted
193+
) public withPerm(ADMIN) {
194+
require(
195+
_transferTypes.length == _fromValidKYC.length &&
196+
_fromValidKYC.length == _toValidKYC.length &&
197+
_toValidKYC.length == _fromRestricted.length &&
198+
_fromRestricted.length == _toRestricted.length,
199+
"Mismatched input lengths"
200+
);
201+
202+
for (uint256 i = 0; i < _transferTypes.length; i++) {
203+
_modifyTransferRequirements(
204+
_transferTypes[i],
205+
_fromValidKYC[i],
206+
_toValidKYC[i],
207+
_fromRestricted[i],
208+
_toRestricted[i]
209+
);
210+
}
211+
}
212+
213+
function _modifyTransferRequirements(
214+
uint256 _transferType,
215+
bool _fromValidKYC,
216+
bool _toValidKYC,
217+
bool _fromRestricted,
218+
bool _toRestricted
219+
) internal {
220+
require(_transferType < 3, "Invalid TransferType");
221+
transferRequirements[_transferType] =
222+
TransferRequirements(
223+
_fromValidKYC,
224+
_toValidKYC,
225+
_fromRestricted,
226+
_toRestricted
227+
);
228+
229+
emit ModifyTransferRequirements(
230+
_transferType,
231+
_fromValidKYC,
232+
_toValidKYC,
233+
_fromRestricted,
234+
_toRestricted
235+
);
236+
}
237+
214238

215239
/**
216240
* @notice Add or remove KYC info of an investor.
@@ -380,31 +404,31 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage
380404
* @notice Internal function used to check whether the KYC of investor is valid
381405
* @param _expiryTime Expiry time of the investor
382406
*/
383-
function _validExpiry(uint64 _expiryTime) internal view returns(bool) {
384-
return (_expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/
407+
function _validExpiry(uint64 _expiryTime) internal view returns(bool valid) {
408+
if (_expiryTime >= uint64(now)) /*solium-disable-line security/no-block-members*/
409+
valid = true;
385410
}
386411

387412
/**
388413
* @notice Internal function used to check whether the lock time of investor is valid
389414
* @param _lockTime Lock time of the investor
390415
*/
391-
function _validLockTime(uint64 _lockTime) internal view returns(bool) {
392-
return (_lockTime <= uint64(now)); /*solium-disable-line security/no-block-members*/
416+
function _validLockTime(uint64 _lockTime) internal view returns(bool valid) {
417+
if (_lockTime <= uint64(now)) /*solium-disable-line security/no-block-members*/
418+
valid = true;
393419
}
394420

395421
/**
396422
* @notice Internal function to adjust times using default values
397423
*/
398424
function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) {
399-
uint64 adjustedFromTime = _fromTime;
400-
uint64 adjustedToTime = _toTime;
401425
if (_fromTime == 0) {
402-
adjustedFromTime = defaults.fromTime;
426+
_fromTime = defaults.fromTime;
403427
}
404428
if (_toTime == 0) {
405-
adjustedToTime = defaults.toTime;
429+
_toTime = defaults.toTime;
406430
}
407-
return (adjustedFromTime, adjustedToTime);
431+
return (_fromTime, _toTime);
408432
}
409433

410434
function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) {

contracts/modules/TransferManager/GTM/GeneralTransferManagerProxy.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleSto
2626
{
2727
require(_implementation != address(0), "Implementation address should not be 0x");
2828
_upgradeTo(_version, _implementation);
29+
transferRequirements[0] = TransferRequirements(true, true, true, true);
30+
transferRequirements[1] = TransferRequirements(false, true, false, false);
31+
transferRequirements[2] = TransferRequirements(true, false, false, false);
2932
}
3033

3134
}

contracts/modules/TransferManager/GTM/GeneralTransferManagerStorage.sol

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ contract GeneralTransferManagerStorage {
1313
//Address from which issuances come
1414
address public issuanceAddress;
1515

16-
// //from and to timestamps that an investor can send / receive tokens respectively
17-
// // Now Stored in DataStore
18-
// struct TimeRestriction {
19-
// uint64 fromTime;
20-
// uint64 toTime;
21-
// uint64 expiryTime;
22-
// uint8 added;
23-
// }
24-
2516
// Allows all TimeRestrictions to be offset
2617
struct Defaults {
2718
uint64 fromTime;
@@ -34,13 +25,13 @@ contract GeneralTransferManagerStorage {
3425
// Map of used nonces by customer
3526
mapping(address => mapping(uint256 => bool)) public nonceMap;
3627

37-
//If true, there are no transfer restrictions, for any addresses
38-
bool public allowAllTransfers = false;
39-
//If true, time lock is ignored for transfers (address must still be on whitelist)
40-
bool public allowAllWhitelistTransfers = false;
41-
//If true, time lock is ignored for issuances (address must still be on whitelist)
42-
bool public allowAllWhitelistIssuances = true;
43-
//If true, time lock is ignored for burn transactions
44-
bool public allowAllBurnTransfers = false;
28+
struct TransferRequirements {
29+
bool fromValidKYC;
30+
bool toValidKYC;
31+
bool fromRestricted;
32+
bool toRestricted;
33+
}
4534

35+
mapping(uint256 => TransferRequirements) public transferRequirements;
36+
// General = 0, Issuance = 1, Redemption = 2
4637
}

0 commit comments

Comments
 (0)