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

Single Trade Volume Restriction #262

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a48ae40
Initial Setup
subramanianv Sep 18, 2018
90c9c54
deploy function
subramanianv Sep 18, 2018
62f4d6c
Implement VerfyTransfer Function and also Permissions
subramanianv Sep 18, 2018
b1e882a
Fix lookup errors
subramanianv Sep 18, 2018
f6b9c7a
Single Trade Volume Tests WIP
subramanianv Sep 25, 2018
c7f5012
Complete tests
subramanianv Sep 26, 2018
939d0c0
Update comments
subramanianv Sep 26, 2018
5f5f416
Merge branch 'development-1.5.0' of https://github.com/PolymathNetwor…
subramanianv Sep 26, 2018
4e1010f
change implementation according to development-1.5 branch
subramanianv Sep 26, 2018
c87b5c2
Tests refactored
subramanianv Sep 26, 2018
889db0e
Added multi functions
subramanianv Sep 27, 2018
f399728
added comments for singletradevolumeRestrictionFactory
subramanianv Sep 27, 2018
74fe6ed
Add token info script
adamdossa Sep 27, 2018
bb2d279
Merge pull request #282 from PolymathNetwork/token-info-script
pabloruiz55 Sep 27, 2018
a233e46
Added more tests
subramanianv Sep 27, 2018
2f2b19d
More tests
subramanianv Sep 27, 2018
6738b00
Changes from the review and more tests
subramanianv Sep 27, 2018
8aa2560
More tests
subramanianv Sep 27, 2018
47c82fd
More tests
subramanianv Sep 27, 2018
1814326
Merge branch 'development-1.5.0' of https://github.com/PolymathNetwor…
subramanianv Sep 27, 2018
d823228
Changes after the merge
subramanianv Sep 28, 2018
7a56664
Changes from the review
subramanianv Oct 1, 2018
1e46254
Merge https://github.com/PolymathNetwork/polymath-core into singleTra…
subramanianv Oct 1, 2018
8c344e3
Merge branch 'development-1.5.0' of https://github.com/PolymathNetwor…
subramanianv Oct 1, 2018
6b328dc
Add tests
subramanianv Oct 1, 2018
477a858
Merge branch 'development-1.5.0' of https://github.com/PolymathNetwor…
subramanianv Oct 3, 2018
09015da
Changes from the review
subramanianv Oct 3, 2018
c6722fd
Deleted tokeninfo.js
subramanianv Oct 3, 2018
b2c717d
Merge branch 'development-1.5.0' into singleTradeVolumeRestriction
adamdossa Oct 4, 2018
9da57ab
Update 2_deploy_contracts.js
adamdossa Oct 4, 2018
d30f0fb
Merge branch 'development-1.5.0' into singleTradeVolumeRestriction
pabloruiz55 Oct 4, 2018
77b3410
Update SingleTradeVolumeRestrictionManager.sol
adamdossa Oct 4, 2018
786d705
Update 2_deploy_contracts.js
adamdossa Oct 4, 2018
149f56d
Update w_single_trade_volume_restriction.js
adamdossa Oct 4, 2018
28c3315
minor fixes
SatyamSB Oct 5, 2018
61f268d
Merge branch 'development-1.5.0' into singleTradeVolumeRestriction
adamdossa Oct 5, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
pragma solidity ^0.4.24;
import "./ITransferManager.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
* @title Transfer Manager for limiting volume of tokens in a single trade
*/

contract SingleTradeVolumeRestrictionManager is ITransferManager {
using SafeMath for uint256;

bytes32 constant public ADMIN = "ADMIN";

bool public isTransferLimitInPercentage;

uint256 public globalTransferLimitInTokens;

// should be multipled by 10^16. if the transfer percentage is 20%, then globalTransferLimitInPercentage should be 20*10^16
uint256 public globalTransferLimitInPercentage;

//mapping to store the wallets that are exempted from the volume restriction
mapping(address => bool) public exemptWallets;

//addresses on this list have special transfer restrictions apart from global
mapping(address => uint) public specialTransferLimitsInTokens;

mapping(address => uint) public specialTransferLimitsInPercentages;

event ExemptWalletAdded(address _wallet);
event ExemptWalletRemoved(address _wallet);
event TransferLimitInTokensSet(address _wallet, uint256 _amount);
event TransferLimitInPercentageSet(address _wallet, uint _percentage);
event TransferLimitInPercentageRemoved(address _wallet);
event TransferLimitInTokensRemoved(address _wallet);
event GlobalTransferLimitInTokensSet(uint256 _amount, uint256 _oldAmount);
event GlobalTransferLimitInPercentageSet(uint256 _percentage, uint256 _oldPercentage);
event TransferLimitChangedToTokens();
event TransferLimitChangedtoPercentage();

/**
* @notice Constructor
* @param _securityToken Address of the security token
* @param _polyAddress Address of the polytoken
*/
constructor(address _securityToken, address _polyAddress) public
Module(_securityToken, _polyAddress)
{

}

/// @notice Used to verify the transfer transaction according to the rule implemented in the transfer manager
function verifyTransfer(address _from, address /* _to */, uint256 _amount, bytes /* _data */, bool /* _isTransfer */) public returns(Result) {
bool validTransfer;

if (exemptWallets[_from] || paused) return Result.NA;

if (isTransferLimitInPercentage) {
if(specialTransferLimitsInPercentages[_from] > 0) {
validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= specialTransferLimitsInPercentages[_from];
} else {
validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= globalTransferLimitInPercentage;
}
} else {
if (specialTransferLimitsInTokens[_from] > 0) {
validTransfer = _amount <= specialTransferLimitsInTokens[_from];
} else {
validTransfer = _amount <= globalTransferLimitInTokens;
}
}
if (validTransfer) return Result.NA;
return Result.INVALID;
}

/**
* @notice Used to intialize the variables of the contract
* @param _isTransferLimitInPercentage true if the transfer limit is in percentage else false
* @param _globalTransferLimitInPercentageOrToken transfer limit per single transaction.
*/
function configure(bool _isTransferLimitInPercentage, uint256 _globalTransferLimitInPercentageOrToken) public onlyFactory {
isTransferLimitInPercentage = _isTransferLimitInPercentage;
if (isTransferLimitInPercentage) {
changeGlobalLimitInPercentage(_globalTransferLimitInPercentageOrToken);
} else {
changeGlobalLimitInTokens(_globalTransferLimitInPercentageOrToken);
}
}

/**
* @notice Changes the manager to use transfer limit as Percentages
* @param _newGlobalTransferLimitInPercentage uint256 new global Transfer Limit In Percentage.
* @dev specialTransferLimits set for wallets have to re-configured
*/
function changeTransferLimitToPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) {
require(!isTransferLimitInPercentage, "Transfer limit already in percentage");
isTransferLimitInPercentage = true;
changeGlobalLimitInPercentage(_newGlobalTransferLimitInPercentage);
emit TransferLimitChangedtoPercentage();
}

/**
* @notice Changes the manager to use transfer limit as tokens
* @param _newGlobalTransferLimit uint256 new global Transfer Limit in tokens.
* @dev specialTransferLimits set for wallets have to re-configured
*/
function changeTransferLimitToTokens(uint _newGlobalTransferLimit) public withPerm(ADMIN) {
require(isTransferLimitInPercentage, "Transfer limit already in tokens");
isTransferLimitInPercentage = false;
changeGlobalLimitInTokens(_newGlobalTransferLimit);
emit TransferLimitChangedToTokens();
}
/**
* @notice Change the global transfer limit
* @param _newGlobalTransferLimitInTokens new transfer limit in tokens
* @dev This function can be used only when The manager is configured to use limits in tokens
*/
function changeGlobalLimitInTokens(uint256 _newGlobalTransferLimitInTokens) public withPerm(ADMIN) {
require(!isTransferLimitInPercentage, "Transfer limit not set in tokens");
require(_newGlobalTransferLimitInTokens > 0, "Transfer limit has to greater than zero");
emit GlobalTransferLimitInTokensSet(_newGlobalTransferLimitInTokens, globalTransferLimitInTokens);
globalTransferLimitInTokens = _newGlobalTransferLimitInTokens;

}

/**
* @notice Change the global transfer limit
* @param _newGlobalTransferLimitInPercentage new transfer limit in percentage.
* Multiply the percentage by 10^16. Eg 22% will be 22*10^16
* @dev This function can be used only when The manager is configured to use limits in percentage
*/
function changeGlobalLimitInPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) {
require(isTransferLimitInPercentage, "Transfer limit not set in Percentage");
require(_newGlobalTransferLimitInPercentage > 0 && _newGlobalTransferLimitInPercentage <= 100 * 10 ** 16);
emit GlobalTransferLimitInPercentageSet(_newGlobalTransferLimitInPercentage, globalTransferLimitInPercentage);
globalTransferLimitInPercentage = _newGlobalTransferLimitInPercentage;

}

/**
* @notice add an exempt wallet
* @param _wallet exempt wallet address
*/
function addExemptWallet(address _wallet) public withPerm(ADMIN) {
require(_wallet != address(0), "Wallet address cannot be a zero address");
exemptWallets[_wallet] = true;
emit ExemptWalletAdded(_wallet);
}

/**
* @notice remove an exempt wallet
* @param _wallet exempt wallet address
*/
function removeExemptWallet(address _wallet) public withPerm(ADMIN) {
require(_wallet != address(0), "Wallet address cannot be a zero address");
exemptWallets[_wallet] = false;
emit ExemptWalletRemoved(_wallet);
}

/**
* @notice adds an array of exempt wallet
* @param _wallets array of exempt wallet addresses
*/
function addExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
for (uint256 i = 0; i < _wallets.length; i++) {
addExemptWallet(_wallets[i]);
}
}

/**
* @notice removes an array of exempt wallet
* @param _wallets array of exempt wallet addresses
*/
function removeExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
for (uint256 i = 0; i < _wallets.length; i++) {
removeExemptWallet(_wallets[i]);
}
}

/**
* @notice set transfer limit per wallet
* @param _wallet wallet address
* @param _transferLimit transfer limit for the wallet in tokens
* @dev the manager has to be configured to use limits in tokens
*/
function setTransferLimitInTokens(address _wallet, uint _transferLimit) public withPerm(ADMIN) {
require(_transferLimit > 0, "Transfer limit has to be greater than 0");
require(!isTransferLimitInPercentage, "Transfer limit not in token amount");
specialTransferLimitsInTokens[_wallet] = _transferLimit;
emit TransferLimitInTokensSet(_wallet, _transferLimit);
}

/**
* @notice set transfer limit for a wallet
* @param _wallet wallet address
* @param _transferLimitInPercentage transfer limit for the wallet in percentage.
* Multiply the percentage by 10^16. Eg 22% will be 22*10^16
* @dev The manager has to be configured to use percentages
*/
function setTransferLimitInPercentage(address _wallet, uint _transferLimitInPercentage) public withPerm(ADMIN) {
require(isTransferLimitInPercentage, "Transfer limit not in percentage");
require(_transferLimitInPercentage > 0 && _transferLimitInPercentage <= 100 * 10 ** 16, "Transfer limit not in required range");
specialTransferLimitsInPercentages[_wallet] = _transferLimitInPercentage;
emit TransferLimitInPercentageSet(_wallet, _transferLimitInPercentage);
}


/**
* @notice removes transfer limit set in percentage for a wallet
* @param _wallet wallet address
*/
function removeTransferLimitInPercentage(address _wallet) public withPerm(ADMIN) {
require(specialTransferLimitsInPercentages[_wallet] > 0 , "Wallet Address does not have a transfer limit");
specialTransferLimitsInPercentages[_wallet] = 0;
emit TransferLimitInPercentageRemoved(_wallet);
}

/**
* @notice removes transfer limit set in tokens for a wallet
* @param _wallet wallet address
*/
function removeTransferLimitInTokens(address _wallet) public withPerm(ADMIN) {
require(specialTransferLimitsInTokens[_wallet] > 0 , "Wallet Address does not have a transfer limit");
specialTransferLimitsInTokens[_wallet] = 0;
emit TransferLimitInTokensRemoved(_wallet);
}

/**
* @notice sets transfer limits for an array of wallet
* @param _wallets array of wallet addresses
* @param _transferLimits array of transfer limits for each wallet in tokens
* @dev The manager has to be configured to use tokens as limit
*/
function setTransferLimitInTokensMulti(address[] _wallets, uint[] _transferLimits) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
require(_wallets.length == _transferLimits.length);
for (uint256 i=0; i < _wallets.length; i++ ) {
setTransferLimitInTokens(_wallets[i], _transferLimits[i]);
}
}

/**
* @notice sets transfer limits for an array of wallet
* @param _wallets array of wallet addresses
* @param _transferLimitsInPercentage array of transfer limits for each wallet in percentages
* The percentage has to be multipled by 10 ** 16. Eg: 20% would be 20 * 10 ** 16
* @dev The manager has to be configured to use percentage as limit
*/
function setTransferLimitInPercentageMulti(address[] _wallets, uint[] _transferLimitsInPercentage) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
require(_wallets.length == _transferLimitsInPercentage.length);
for (uint256 i=0; i < _wallets.length; i++) {
setTransferLimitInPercentage(_wallets[i], _transferLimitsInPercentage[i]);
}
}

/**
* @notice removes transfer limits set in tokens for an array of wallet
* @param _wallets array of wallet addresses
*/
function removeTransferLimitInTokensMulti(address[] _wallets) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
for (uint i = 0; i < _wallets.length; i++) {
removeTransferLimitInTokens(_wallets[i]);
}
}

/**
* @notice removes transfer limits set in percentage for an array of wallet
* @param _wallets array of wallet addresses
*/
function removeTransferLimitInPercentageMulti(address[] _wallets) public withPerm(ADMIN) {
require(_wallets.length > 0, "Wallets cannot be empty");
for (uint i = 0; i < _wallets.length; i++) {
removeTransferLimitInPercentage(_wallets[i]);
}
}

/**
* @notice This function returns the signature of configure function
*/
function getInitFunction() public pure returns (bytes4) {
return bytes4(keccak256("configure(bool,uint256)"));
}

/**
* @notice Return the permissions flag that are associated with SingleTradeVolumeRestrictionManager
*/
function getPermissions() public view returns(bytes32[]) {
bytes32[] memory allPermissions = new bytes32[](1);
allPermissions[0] = ADMIN;
return allPermissions;
}
}
Loading