Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple module types #305

Merged
merged 32 commits into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fc0bace
WIP
adamdossa Oct 2, 2018
a925a8c
Fixes
adamdossa Oct 2, 2018
4838de7
Merge branch 'development-1.5.0' into support_multiple_module_types
adamdossa Oct 2, 2018
59cb476
Size too big...
adamdossa Oct 2, 2018
ce06984
WIP
adamdossa Oct 3, 2018
ceed74e
WIP
adamdossa Oct 3, 2018
e7caf0d
Go back to in-lined internals
adamdossa Oct 3, 2018
f1c6aa4
Merge branch 'development-1.5.0' into support_multiple_module_types
adamdossa Oct 3, 2018
0a00f95
Remove merge cruft
adamdossa Oct 3, 2018
85a8ba6
More merge cruft
adamdossa Oct 3, 2018
f31a001
WIP fixes
adamdossa Oct 3, 2018
a37a776
Still too big
adamdossa Oct 3, 2018
5c5dbd5
Working
adamdossa Oct 3, 2018
80bfbb1
Remove commented lines
adamdossa Oct 3, 2018
5a7657b
Fix test cases
adamdossa Oct 3, 2018
5278696
More fixes
adamdossa Oct 3, 2018
3b0f0be
Remove kludge
adamdossa Oct 3, 2018
b91c14e
Fix some more tests
adamdossa Oct 3, 2018
b37b605
move investors data and logic into the library
SatyamSB Oct 4, 2018
11f6e60
minor naming fix
SatyamSB Oct 4, 2018
e7a290d
cleanup
SatyamSB Oct 4, 2018
6fe5614
Merge branch 'support_multiple_module_types' into some-changes-adampr
SatyamSB Oct 4, 2018
2b50c16
add some improvements
SatyamSB Oct 4, 2018
d5e0a7f
added a missing semi-colon
maxsam4 Oct 4, 2018
f4869dd
Fixes based on comments
adamdossa Oct 4, 2018
a810f91
Remove empty module
adamdossa Oct 4, 2018
2952dc4
Add forceBurn to fuzz testing for checkpoints
adamdossa Oct 4, 2018
acbc3f5
resolve conflicts
SatyamSB Oct 4, 2018
7e2859b
minor fix
SatyamSB Oct 4, 2018
6d8bcee
remove investorCount
SatyamSB Oct 4, 2018
e4817d3
Merge pull request #314 from PolymathNetwork/some-changes-adampr
satyamakgec Oct 4, 2018
1b4a549
Small update
adamdossa Oct 4, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions contracts/ModuleRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,18 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage {
}
require(getUint(Encoder.getKey('registry', _moduleFactory)) == 0, "Module factory should not be pre-registered");
IModuleFactory moduleFactory = IModuleFactory(_moduleFactory);
uint8 moduleType = moduleFactory.getType();
require(moduleType != 0, "Factory moduleType should not equal to 0");
//Enforce type uniqueness
uint256 i;
uint256 j;
uint8[] memory moduleTypes = moduleFactory.getTypes();
for (i = 0; i < moduleTypes.length; i++) {
adamdossa marked this conversation as resolved.
Show resolved Hide resolved
for (j = 0; j < i; j++) {
require(moduleTypes[i] != moduleTypes[j], "Type mismatch");
}
}
require(moduleTypes.length != 0, "Factory must have type");
// NB - here we index by the first type of the module.
uint8 moduleType = moduleFactory.getTypes()[0];
set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType));
set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length));
pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory);
Expand Down
2 changes: 1 addition & 1 deletion contracts/SecurityTokenRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
return true;
}

function _tickerStatus(string _ticker) internal returns(bool) {
function _tickerStatus(string _ticker) internal view returns(bool) {
return getBool(Encoder.getKey("registeredTickers_status", _ticker));
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IModuleFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface IModuleFactory {
/**
* @notice Type of the Module factory
*/
function getType() external view returns(uint8);
function getTypes() external view returns(uint8[]);

/**
* @notice Get the name of the Module
Expand Down
22 changes: 12 additions & 10 deletions contracts/interfaces/ISecurityToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ interface ISecurityToken {
* @notice Burn function used to burn the securityToken
* @param _value No. of tokens that get burned
*/
function burn(uint256 _value) external returns (bool success);
function burn(uint256 _value) external;
adamdossa marked this conversation as resolved.
Show resolved Hide resolved

/**
* @notice Burn function used to burn the securityToken on behalf of someone else
* @param _from Address for whom to burn tokens
* @param _value No. of token that get burned
*/
function burnFrom(address _from, uint256 _value) external returns (bool success);
function burnFrom(address _from, uint256 _value) external;

event Minted(address indexed _to, uint256 _value);
event Burnt(address indexed _burner, uint256 _value);
Expand Down Expand Up @@ -101,7 +101,7 @@ interface ISecurityToken {
* NB - this length may differ from investorCount if the list has not been pruned of zero-balance investors
* @return length
*/
function getInvestorsLength() external view returns (uint256);
function getInvestors() external view returns (address[]);

/**
* @notice gets current checkpoint ID
Expand Down Expand Up @@ -180,12 +180,6 @@ interface ISecurityToken {
*/
function mintMulti(address[] _investors, uint256[] _values) external returns (bool success);

/**
* @notice used to set the token Burner address. It can only be called by the owner
* @param _tokenBurner Address of the token burner contract
*/
function setTokenBurner(address _tokenBurner) external;

/**
* @notice Removes a module attached to the SecurityToken
* @param _module address of module to archive
Expand Down Expand Up @@ -231,7 +225,15 @@ interface ISecurityToken {
* @param _value amount of tokens to transfer
* @param _data data attached to the transfer by controller to emit in event
*/
function forceTransfer(address _from, address _to, uint256 _value, bytes _data) external returns(bool);
function forceTransfer(address _from, address _to, uint256 _value, bytes _data) external;

/**
* @notice Use by a controller to execute a foced burn
* @param _from address from which to take tokens
* @param _value amount of tokens to transfer
* @param _data data attached to the transfer by controller to emit in event
*/
function forceBurn(address _from, uint256 _value, bytes _data) external;

/**
* @notice Use by the issuer to permanently disable controller functionality
Expand Down
10 changes: 0 additions & 10 deletions contracts/interfaces/ITokenBurner.sol

This file was deleted.

13 changes: 6 additions & 7 deletions contracts/libraries/Encoder.sol
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
pragma solidity ^0.4.24;


library Encoder {

function getKey(string _key) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key)));
}

function getKey(string _key1, address _key2) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key1, _key2)));
}

function getKey(string _key1, string _key2) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key1, _key2)));
}

function getKey(string _key1, uint256 _key2) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key1, _key2)));
}

function getKey(string _key1, bytes32 _key2) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key1, _key2)));
}

function getKey(string _key1, bool _key2) internal pure returns (bytes32) {
return bytes32(keccak256(abi.encodePacked(_key1, _key2)));
}

}
}
152 changes: 152 additions & 0 deletions contracts/libraries/TokenLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
pragma solidity ^0.4.24;

import "../modules/PermissionManager/IPermissionManager.sol";

library TokenLib {

// Struct for module data
struct ModuleData {
bytes32 name;
address module;
address moduleFactory;
bool isArchived;
uint8[] moduleTypes;
uint256[] moduleIndexes;
uint256 nameIndex;
mapping (uint8 => uint256) moduleIndex;
adamdossa marked this conversation as resolved.
Show resolved Hide resolved
}

// Structures to maintain checkpoints of balances for governance / dividends
struct Checkpoint {
uint256 checkpointId;
uint256 value;
}

// Emit when Module get archived from the securityToken
event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp);
// Emit when Module get unarchived from the securityToken
event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp);

/**
* @notice Archives a module attached to the SecurityToken
* @param _moduleData storage data
* @param _module address of module to archive
*/
function archiveModule(ModuleData storage _moduleData, address _module) public {
require(!_moduleData.isArchived, "Module archived");
require(_moduleData.module != address(0), "Module missing");
emit ModuleArchived(_moduleData.moduleTypes, _module, now);
_moduleData.isArchived = true;
}

/**
* @notice Unarchives a module attached to the SecurityToken
* @param _moduleData storage data
* @param _module address of module to unarchive
*/
function unarchiveModule(ModuleData storage _moduleData, address _module) public {
require(_moduleData.isArchived, "Module unarchived");
emit ModuleUnarchived(_moduleData.moduleTypes, _module, now);
_moduleData.isArchived = false;
}

/**
* @notice Validate permissions with PermissionManager if it exists, If no Permission return false
* @dev Note that IModule withPerm will allow ST owner all permissions anyway
* @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions)
* @param _modules storage data
* @param _delegate address of delegate
* @param _module address of PermissionManager module
* @param _perm the permissions
* @return success
*/
function checkPermission(address[] storage _modules, address _delegate, address _module, bytes32 _perm) public view returns(bool) {
if (_modules.length == 0) {
return false;
}

for (uint8 i = 0; i < _modules.length; i++) {
if (IPermissionManager(_modules[i]).checkPermission(_delegate, _module, _perm)) {
return true;
}
}

return false;
}

/**
* @notice Queries value at a defined checkpoint
* @param _checkpoints is array of Checkpoint objects
* @param _checkpointId Checkpoint ID to query
* @param _currentValue Current value of checkpoint
* @return uint256
*/
function getValueAt(Checkpoint[] storage _checkpoints, uint256 _checkpointId, uint256 _currentValue) public view returns(uint256) {
//Checkpoint id 0 is when the token is first created - everyone has a zero balance
if (_checkpointId == 0) {
return 0;
}
if (_checkpoints.length == 0) {
return _currentValue;
}
if (_checkpoints[0].checkpointId >= _checkpointId) {
return _checkpoints[0].value;
}
if (_checkpoints[_checkpoints.length - 1].checkpointId < _checkpointId) {
return _currentValue;
}
if (_checkpoints[_checkpoints.length - 1].checkpointId == _checkpointId) {
return _checkpoints[_checkpoints.length - 1].value;
}
uint256 min = 0;
uint256 max = _checkpoints.length - 1;
while (max > min) {
uint256 mid = (max + min) / 2;
if (_checkpoints[mid].checkpointId == _checkpointId) {
max = mid;
break;
}
if (_checkpoints[mid].checkpointId < _checkpointId) {
min = mid + 1;
} else {
max = mid;
}
}
return _checkpoints[max].value;
}

/**
* @notice store the changes to the checkpoint objects
* @param _checkpoints the affected checkpoint object array
* @param _newValue the new value that needs to be stored
*/
function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public {
//No checkpoints set yet
if (_currentCheckpointId == 0) {
return;
}
//No previous checkpoint data - add current balance against checkpoint
if (_checkpoints.length == 0) {
_checkpoints.push(
TokenLib.Checkpoint({
checkpointId: _currentCheckpointId,
value: _newValue
})
);
return;
}
//No new checkpoints since last update
if (_checkpoints[_checkpoints.length - 1].checkpointId == _currentCheckpointId) {
adamdossa marked this conversation as resolved.
Show resolved Hide resolved
return;
}
//New checkpoint, so record balance
_checkpoints.push(
TokenLib.Checkpoint({
checkpointId: _currentCheckpointId,
value: _newValue
})
);
}


}
28 changes: 14 additions & 14 deletions contracts/libraries/VersionUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ pragma solidity ^0.4.24;
*/

library VersionUtils {

/**
* @notice This function is used to validate the version submitted
* @param _current Array holds the present version of ST
* @param _new Array holds the latest version of the ST
* @return bool
* @return bool
*/
function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) {
bool[] memory _temp = new bool[](_current.length);
Expand All @@ -21,16 +21,16 @@ library VersionUtils {
else
_temp[i] = false;
}

for (i = 0; i < _current.length; i++) {
if (i == 0) {
if (_current[i] <= _new[i])
if(_temp[0]) {
if(_temp[0]) {
counter = counter + 3;
break;
} else
counter++;
else
else
return false;
} else {
if (_temp[i-1])
Expand All @@ -49,7 +49,7 @@ library VersionUtils {
* @notice This function use to compare the lower bound with the latest version
* @param _version1 Array holds the lower bound of the version
* @param _version2 Array holds the latest version of the ST
* @return bool
* @return bool
*/
function compareLowerBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) {
require(_version1.length == _version2.length);
Expand All @@ -71,16 +71,16 @@ library VersionUtils {
if (counter == _version1.length - 1)
return true;
else
return false;
return false;
} else
return true;
return true;
}

/**
* @notice This function use to compare the upper bound with the latest version
* @param _version1 Array holds the upper bound of the version
* @param _version2 Array holds the latest version of the ST
* @return bool
* @return bool
*/
function compareUpperBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) {
require(_version1.length == _version2.length);
Expand All @@ -102,12 +102,12 @@ library VersionUtils {
if (counter == _version1.length - 1)
return true;
else
return false;
return false;
} else
return true;
return true;
}


/**
* @notice Use to pack the uint8[] array data into uint24 value
* @param _major Major version
Expand All @@ -129,6 +129,6 @@ library VersionUtils {
_unpackVersion[2] = uint8(_packedVersion);
return _unpackVersion;
}


}

}
Loading