Skip to content

Commit

Permalink
Merge pull request #84 from PolymathNetwork/offchain_whitelist
Browse files Browse the repository at this point in the history
Add off-chain signing ability
  • Loading branch information
satyamakgec authored Apr 24, 2018
2 parents e092196 + 7735bd4 commit e058581
Show file tree
Hide file tree
Showing 11 changed files with 634 additions and 25 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ All notable changes to this project will be documented in this file.

* IModule contract takes the polyToken contract address as the constructor argument to wrapping all the factories with the polyToken contract address.
* `takeFee()` new function introduced to extract the POLY token from the factory. It only be called by the owner of the factory.

* Added ability for issuer to provide a signed piece of data to allow investors to whitelist themselves.

***

[__0.3.1__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __06-04-18__

## Added
* Add `emit` keyword to emit the events.
* Two new variable is added at the time of registeration of ticker. `swarmHash` represents the off-chain data storage location on IPFS and `owner` It reperesent the ethereum address of the owner.
* Two new variable is added at the time of registration of ticker. `swarmHash` represents the off-chain data storage location on IPFS and `owner` It reperesent the ethereum address of the owner.
* `LogRegisterTicker` emits two more variable called `_swarmHash` and `_owner`.
* Two events are added in `GeneralPermissionManager` contract to facilitate the notifications for the UI end.
__`LogChangePermission`__ :Emit when permissions to a delegate get changed.
Expand Down
4 changes: 2 additions & 2 deletions contracts/Migrations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ pragma solidity ^0.4.23;
contract Migrations {

address public owner;

uint public lastCompletedMigration;

modifier restricted() {
require(msg.sender == owner);
_;
}

constructor() public {
function Migrations() public {
owner = msg.sender;
}

Expand Down
10 changes: 5 additions & 5 deletions contracts/interfaces/IModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,29 @@ contract IModule {
modifier withPerm(bytes32 _perm) {
bool isOwner = msg.sender == ISecurityToken(securityToken).owner();
bool isFactory = msg.sender == factory;
require(isOwner||isFactory||ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm));
require(isOwner||isFactory||ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm), "Permission check failed");
_;
}

modifier onlyOwner {
require(msg.sender == ISecurityToken(securityToken).owner());
require(msg.sender == ISecurityToken(securityToken).owner(), "Sender is not owner");
_;
}

modifier onlyFactory {
require(msg.sender == factory);
require(msg.sender == factory, "Sender is not factory");
_;
}

modifier onlyFactoryOwner {
require(msg.sender == IModuleFactory(factory).owner());
require(msg.sender == IModuleFactory(factory).owner(), "Sender is not factory owner");
_;
}

function getPermissions() public view returns(bytes32[]);

function takeFee(uint256 _amount) public withPerm(FEE_ADMIN) returns(bool) {
require(polyToken.transferFrom(address(this), IModuleFactory(factory).owner(), _amount));
require(polyToken.transferFrom(address(this), IModuleFactory(factory).owner(), _amount), "Unable to take fee");
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ contract GeneralPermissionManager is IPermissionManager {
withPerm(CHANGE_PERMISSION)
returns(bool)
{
require(delegateDetails[_delegate] != bytes32(0));
require(delegateDetails[_delegate] != bytes32(0), "Delegate details not set");
perms[_module][_delegate][_perm] = _valid;
emit LogChangePermission(_delegate, _module, _perm, _valid, now);
return true;
Expand Down
41 changes: 39 additions & 2 deletions contracts/modules/TransferManager/GeneralTransferManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ contract GeneralTransferManager is ITransferManager {
//Address from which issuances come
address public issuanceAddress = address(0);

//Address which can sign whitelist changes
address public signingAddress = address(0);

bytes32 public constant WHITELIST = "WHITELIST";
bytes32 public constant FLAGS = "FLAGS";

Expand All @@ -42,6 +45,7 @@ contract GeneralTransferManager is ITransferManager {
event LogAllowAllTransfers(bool _allowAllTransfers);
event LogAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers);
event LogAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances);
event LogChangeSigningAddress(address _signingAddress);

event LogModifyWhitelist(
address _investor,
Expand All @@ -66,6 +70,11 @@ contract GeneralTransferManager is ITransferManager {
emit LogChangeIssuanceAddress(_issuanceAddress);
}

function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) {
signingAddress = _signingAddress;
emit LogChangeSigningAddress(_signingAddress);
}

function changeAllowAllTransfers(bool _allowAllTransfers) public withPerm(FLAGS) {
allowAllTransfers = _allowAllTransfers;
emit LogAllowAllTransfers(_allowAllTransfers);
Expand Down Expand Up @@ -123,13 +132,41 @@ contract GeneralTransferManager is ITransferManager {
uint256[] _fromTimes,
uint256[] _toTimes
) public withPerm(WHITELIST) {
require(_investors.length == _fromTimes.length);
require(_fromTimes.length == _toTimes.length);
require(_investors.length == _fromTimes.length, "Mismatched input lengths");
require(_fromTimes.length == _toTimes.length, "Mismatched input lengths");
for (uint256 i = 0; i < _investors.length; i++) {
modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i]);
}
}

/**
* @dev adds or removes addresses from the whitelist - can be called by anyone with a valid signature
* @param _investor is the address to whitelist
* @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens
* @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others
* @param _validFrom is the time that this signature is valid from
* @param _validTo is the time that this signature is valid until
* @param _v issuer signature
* @param _r issuer signature
* @param _s issuer signature
*/
function modifyWhitelistSigned(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _validFrom, uint256 _validTo, uint8 _v, bytes32 _r, bytes32 _s) public {
require(_validFrom <= now, "ValidFrom is too early");
require(_validTo >= now, "ValidTo is too late");
bytes32 hash = keccak256(this, _investor, _fromTime, _toTime, _validFrom, _validTo);
checkSig(hash, _v, _r, _s);
//Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist
whitelist[_investor] = TimeRestriction(_fromTime, _toTime);
emit LogModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime);
}

function checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view {
//Check that the signature is valid
//sig should be signing - _investor, _fromTime & _toTime and be signed by the issuer address
address signer = ecrecover(keccak256("\x19Ethereum Signed Message:\n32", _hash), _v, _r, _s);
require(signer == ISecurityToken(securityToken).owner() || signer == signingAddress, "Incorrect signer");
}

function getPermissions() public view returns(bytes32[]) {
bytes32[] memory allPermissions = new bytes32[](2);
allPermissions[0] = WHITELIST;
Expand Down
10 changes: 5 additions & 5 deletions contracts/tokens/SecurityToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 {
isModuleType = isModuleType || (modules[_moduleType][i].moduleAddress == msg.sender);
}
if (_fallback && !isModuleType) {
require(msg.sender == owner);
require(msg.sender == owner, "Sender is not owner");
} else {
require(isModuleType);
require(isModuleType, "Sender is not correct module type");
}
_;
}
Expand Down Expand Up @@ -200,9 +200,9 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 {
* @dev allows owner to approve more POLY to one of the modules
*/
function changeModuleBudget(uint8 _moduleType, uint8 _moduleIndex, uint256 _budget) public onlyOwner {
require(_moduleType != 0);
require(_moduleIndex < modules[_moduleType].length);
require(polyToken.approve(modules[_moduleType][_moduleIndex].moduleAddress, _budget));
require(_moduleType != 0, "Module type cannot be zero");
require(_moduleIndex < modules[_moduleType].length, "Incorrrect module index");
require(polyToken.approve(modules[_moduleType][_moduleIndex].moduleAddress, _budget), "Insufficient balance to approve");
emit LogModuleBudgetChanged(_moduleType, modules[_moduleType][_moduleIndex].moduleAddress, _budget);
}

Expand Down
74 changes: 67 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"babel-preset-stage-3": "6.24.1",
"babel-register": "6.26.0",
"bignumber.js": "^6.0.0",
"ethers": "^3.0.15",
"readline-sync": "^1.4.9",
"truffle-contract": "^3.0.4",
"truffle-hdwallet-provider-privkey": "^0.1.0",
Expand All @@ -68,7 +69,7 @@
"ganache-cli": "^6.1.0",
"sol-merger": "^0.1.2",
"solium": "^1.1.6",
"truffle": "^4.1.5",
"truffle": "^4.1.7",
"truffle-wallet-provider": "0.0.5"
}
}
Loading

0 comments on commit e058581

Please sign in to comment.