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

Freeze Minting #224

Merged
merged 6 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
37 changes: 37 additions & 0 deletions contracts/FeatureRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
pragma solidity ^0.4.24;

import "./ReclaimTokens.sol";
import "./interfaces/IFeatureRegistry.sol";

/**
* @title Registry for managing polymath feature switches
*/
contract FeatureRegistry is IFeatureRegistry, ReclaimTokens {

mapping (bytes32 => bool) public featureStatus;

event LogChangeFeatureStatus(string _nameKey, bool _newStatus);

/**
* @notice Get the status of a feature
* @param _nameKey is the key for the feature status mapping
* @return bool
*/
function getFeatureStatus(string _nameKey) external view returns(bool) {
bytes32 key = keccak256(bytes(_nameKey));
return featureStatus[key];
}

/**
* @notice change a feature status
* @param _nameKey is the key for the feature status mapping
* @param _newStatus is the new feature status
*/
function setFeatureStatus(string _nameKey, bool _newStatus) public onlyOwner {
bytes32 key = keccak256(bytes(_nameKey));
require(featureStatus[key] != _newStatus);
thegostep marked this conversation as resolved.
Show resolved Hide resolved
emit LogChangeFeatureStatus(_nameKey, _newStatus);
featureStatus[key] = _newStatus;
}

}
2 changes: 2 additions & 0 deletions contracts/RegistryUpdater.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contract RegistryUpdater is Ownable {
address public moduleRegistry;
address public securityTokenRegistry;
address public tickerRegistry;
address public featureRegistry;
address public polyToken;

constructor (address _polymathRegistry) public {
Expand All @@ -20,6 +21,7 @@ contract RegistryUpdater is Ownable {
moduleRegistry = PolymathRegistry(polymathRegistry).getAddress("ModuleRegistry");
securityTokenRegistry = PolymathRegistry(polymathRegistry).getAddress("SecurityTokenRegistry");
tickerRegistry = PolymathRegistry(polymathRegistry).getAddress("TickerRegistry");
featureRegistry = PolymathRegistry(polymathRegistry).getAddress("FeatureRegistry");
polyToken = PolymathRegistry(polymathRegistry).getAddress("PolyToken");
}

Expand Down
15 changes: 15 additions & 0 deletions contracts/interfaces/IFeatureRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pragma solidity ^0.4.24;

/**
* @title Interface for managing polymath feature switches
*/
interface IFeatureRegistry {

/**
* @notice Get the status of a feature
* @param _nameKey is the key for the feature status mapping
* @return bool
*/
function getFeatureStatus(string _nameKey) external view returns(bool);

}
9 changes: 2 additions & 7 deletions contracts/interfaces/ISecurityToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,9 @@ interface ISecurityToken {
function unfreezeTransfers() external;

/**
* @notice End token minting period permanently for Issuer
* @notice End token minting period permanently
*/
function finishMintingIssuer() external;

/**
* @notice End token minting period permanently for STOs
*/
function finishMintingSTO() external;
function freezeMinting() external;

/**
* @notice mints new tokens and assigns them to the target _investor.
Expand Down
77 changes: 34 additions & 43 deletions contracts/tokens/SecurityToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "../interfaces/IPolyToken.sol";
import "../interfaces/IModule.sol";
import "../interfaces/IModuleFactory.sol";
import "../interfaces/IModuleRegistry.sol";
import "../interfaces/IFeatureRegistry.sol";
import "../modules/TransferManager/ITransferManager.sol";
import "../modules/PermissionManager/IPermissionManager.sol";
import "../interfaces/ITokenBurner.sol";
Expand Down Expand Up @@ -49,8 +50,11 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
// Reference to token burner contract
ITokenBurner public tokenBurner;

// Use to halt all the transactions
bool public freeze = false;
// Use to temporarily halt all transactions
bool public transfersFrozen;
thegostep marked this conversation as resolved.
Show resolved Hide resolved

// Use to permanently halt all minting
bool public mintingFrozen;

struct ModuleData {
bytes32 name;
Expand All @@ -66,9 +70,6 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
mapping (address => Checkpoint[]) public checkpointBalances;
Checkpoint[] public checkpointTotalSupply;

bool public finishedIssuerMinting = false;
bool public finishedSTOMinting = false;

mapping (bytes4 => bool) transferFunctions;

// Module list should be order agnostic!
Expand Down Expand Up @@ -97,14 +98,12 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
event LogModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp);
// Emit when the budget allocated to a module is changed
event LogModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _budget);
// Emit when all the transfers get freeze
event LogFreezeTransfers(bool _freeze, uint256 _timestamp);
// Emit when transfers are frozen or unfrozen
event LogFreezeTransfers(bool _status, uint256 _timestamp);
// Emit when new checkpoint created
event LogCheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp);
// Emit when the minting get finished for the Issuer
event LogFinishMintingIssuer(uint256 _timestamp);
// Emit when the minting get finished for the STOs
event LogFinishMintingSTO(uint256 _timestamp);
// Emit when is permanently frozen by the issuer
event LogFreezeMinting(uint256 _timestamp);
// Change the STR address in the event of a upgrade
event LogChangeSTRAddress(address indexed _oldAddress, address indexed _newAddress);
// Events to log minting and burning
Expand Down Expand Up @@ -135,14 +134,13 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
_;
}

// Checks whether the minting is allowed or not, check for the owner if owner is no the msg.sender then check
// for the finishedSTOMinting flag because only STOs and owner are allowed for minting
modifier isMintingAllowed() {
if (msg.sender == owner) {
require(!finishedIssuerMinting, "Minting is finished for Issuer");
} else {
require(!finishedSTOMinting, "Minting is finished for STOs");
}
require(!mintingFrozen, "Minting is permanently frozen");
_;
}

modifier isEnabled(string _nameKey) {
require(IFeatureRegistry(featureRegistry).getFeatureStatus(_nameKey));
_;
}

Expand Down Expand Up @@ -381,21 +379,21 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
}

/**
* @notice freeze all the transfers
* @notice freeze transfers
*/
function freezeTransfers() external onlyOwner {
require(!freeze);
freeze = true;
emit LogFreezeTransfers(freeze, now);
require(!transfersFrozen);
transfersFrozen = true;
emit LogFreezeTransfers(true, now);
}

/**
* @notice un-freeze all the transfers
* @notice unfreeze transfers
*/
function unfreezeTransfers() external onlyOwner {
require(freeze);
freeze = false;
emit LogFreezeTransfers(freeze, now);
require(transfersFrozen);
transfersFrozen = false;
emit LogFreezeTransfers(false, now);
}

/**
Expand Down Expand Up @@ -486,7 +484,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
* @return bool
*/
function verifyTransfer(address _from, address _to, uint256 _amount) public checkGranularity(_amount) returns (bool) {
if (!freeze) {
if (!transfersFrozen) {
bool isTransfer = false;
if (transferFunctions[getSig(msg.data)]) {
isTransfer = true;
Expand Down Expand Up @@ -515,26 +513,19 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
}

/**
* @notice End token minting period permanently for Issuer
*/
function finishMintingIssuer() external onlyOwner {
finishedIssuerMinting = true;
emit LogFinishMintingIssuer(now);
}

/**
* @notice End token minting period permanently for STOs
* @notice Permanently freeze minting of this security token.
* @dev It MUST NOT be possible to increase `totalSuppy` after this function is called.
*/
function finishMintingSTO() external onlyOwner {
finishedSTOMinting = true;
emit LogFinishMintingSTO(now);
function freezeMinting() external isMintingAllowed() isEnabled("freezeMintingAllowed") onlyOwner {
mintingFrozen = true;
emit LogFreezeMinting(now);
}

/**
* @notice mints new tokens and assigns them to the target _investor.
* @dev Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet)
* @param _investor Address to whom the minted tokens will be dilivered
* @param _amount Number of tokens get minted
* @dev Can only be called by the issuer or STO attached to the token
* @param _investor Address where the minted tokens will be delivered
* @param _amount Number of tokens be minted
* @return success
*/
function mint(address _investor, uint256 _amount) public onlyModule(STO_KEY, true) checkGranularity(_amount) isMintingAllowed() returns (bool success) {
Expand All @@ -552,7 +543,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr

/**
* @notice mints new tokens and assigns them to the target _investor.
* Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet)
* @dev Can only be called by the issuer or STO attached to the token.
* @param _investors A list of addresses to whom the minted tokens will be dilivered
* @param _amounts A list of number of tokens get minted and transfer to corresponding address of the investor from _investor[] list
* @return success
Expand Down
44 changes: 26 additions & 18 deletions migrations/2_deploy_contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFac
const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol')
const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol')
const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol')
const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol');
const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol')
const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol')
const TickerRegistry = artifacts.require('./TickerRegistry.sol')
const FeatureRegistry = artifacts.require('./FeatureRegistry.sol')
const STFactory = artifacts.require('./tokens/STFactory.sol')
const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol')
const MockOracle = artifacts.require('./MockOracle.sol')
Expand Down Expand Up @@ -179,6 +180,12 @@ module.exports = function (deployer, network, accounts) {
}).then(() => {
// Assign the address into the SecurityTokenRegistry key
return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistry.address, {from: PolymathAccount});
}).then(() => {
// K) Deploy the FeatureRegistry contract to control feature switches
return deployer.deploy(FeatureRegistry, PolymathRegistry.address, {from: PolymathAccount});
}).then(() => {
// Assign the address into the FeatureRegistry key
return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, {from: PolymathAccount});
}).then(() => {
// Update all addresses into the registry contract by calling the function updateFromregistry
return SecurityTokenRegistry.at(SecurityTokenRegistry.address).updateFromRegistry({from: PolymathAccount});
Expand Down Expand Up @@ -219,28 +226,29 @@ module.exports = function (deployer, network, accounts) {
}).then(() => {
console.log('\n');
console.log(`
-------------------- Polymath Network Smart Contracts: --------------------
PolymathRegistry: ${PolymathRegistry.address}
TickerRegistry: ${TickerRegistry.address}
ModuleRegistry: ${ModuleRegistry.address}
SecurityTokenRegistry: ${SecurityTokenRegistry.address}
--------------------- Polymath Network Smart Contracts: ---------------------
PolymathRegistry: ${PolymathRegistry.address}
TickerRegistry: ${TickerRegistry.address}
SecurityTokenRegistry: ${SecurityTokenRegistry.address}
ModuleRegistry: ${ModuleRegistry.address}
FeatureRegistry: ${FeatureRegistry.address}

ETHOracle: ${ETHOracle.address}
POLYOracle: ${POLYOracle.address}
ETHOracle: ${ETHOracle}
POLYOracle: ${POLYOracle}

STFactory: ${STFactory.address}
GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address}
GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address}
STFactory: ${STFactory.address}
GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address}
GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address}

CappedSTOFactory: ${CappedSTOFactory.address}
USDTieredSTOFactory: ${USDTieredSTOFactory.address}
CappedSTOFactory: ${CappedSTOFactory.address}
USDTieredSTOFactory: ${USDTieredSTOFactory.address}

CountTransferManagerFactory: ${CountTransferManagerFactory.address}
PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address}
CountTransferManagerFactory: ${CountTransferManagerFactory.address}
PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address}

EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address}
ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address}
---------------------------------------------------------------------------
EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address}
ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address}
-----------------------------------------------------------------------------
`);
console.log('\n');
// -------- END OF POLYMATH NETWORK Configuration -------//
Expand Down
44 changes: 31 additions & 13 deletions test/b_capped_sto.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const ModuleRegistry = artifacts.require('./ModuleRegistry.sol');
const SecurityToken = artifacts.require('./SecurityToken.sol');
const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol');
const TickerRegistry = artifacts.require('./TickerRegistry.sol');
const FeatureRegistry = artifacts.require('./FeatureRegistry.sol');
const STFactory = artifacts.require('./STFactory.sol');
const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol');
const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol');
Expand Down Expand Up @@ -47,6 +48,7 @@ contract('CappedSTO', accounts => {
let I_GeneralTransferManager;
let I_ModuleRegistry;
let I_TickerRegistry;
let I_FeatureRegistry;
let I_SecurityTokenRegistry;
let I_CappedSTOFactory;
let I_STFactory;
Expand Down Expand Up @@ -236,25 +238,41 @@ contract('CappedSTO', accounts => {
"SecurityTokenRegistry contract was not deployed",
);

// Step 10: update the registries addresses from the PolymathRegistry contract
// Step 10: Deploy the FeatureRegistry

I_FeatureRegistry = await FeatureRegistry.new(
I_PolymathRegistry.address,
{
from: account_polymath
});
await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath});

assert.notEqual(
I_FeatureRegistry.address.valueOf(),
"0x0000000000000000000000000000000000000000",
"FeatureRegistry contract was not deployed",
);

// Step 11: update the registries addresses from the PolymathRegistry contract
await I_SecurityTokenRegistry.updateFromRegistry({from: account_polymath});
await I_ModuleRegistry.updateFromRegistry({from: account_polymath});
await I_TickerRegistry.updateFromRegistry({from: account_polymath});

// Printing all the contract addresses
console.log(`
-------------------- Polymath Network Smart Contracts: --------------------
PolymathRegistry: ${I_PolymathRegistry.address}
TickerRegistry: ${I_TickerRegistry.address}
SecurityTokenRegistry: ${I_SecurityTokenRegistry.address}
ModuleRegistry: ${I_ModuleRegistry.address}

STFactory: ${I_STFactory.address}
GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address}
GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address}

CappedSTOFactory: ${I_CappedSTOFactory.address}
---------------------------------------------------------------------------
--------------------- Polymath Network Smart Contracts: ---------------------
PolymathRegistry: ${PolymathRegistry.address}
TickerRegistry: ${TickerRegistry.address}
SecurityTokenRegistry: ${SecurityTokenRegistry.address}
ModuleRegistry: ${ModuleRegistry.address}
FeatureRegistry: ${FeatureRegistry.address}

STFactory: ${STFactory.address}
GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address}
GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address}

CappedSTOFactory: ${I_CappedSTOFactory.address}
-----------------------------------------------------------------------------
`);
});

Expand Down
Loading