From 807de458c16481019ba6152e2b190694964843bc Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 4 Sep 2018 10:33:18 +0100 Subject: [PATCH] Corl Change & MATM update --- contracts/modules/STO/USDTieredSTO.sol | 30 ++++++++++++++++--- .../ManualApprovalTransferManager.sol | 4 +-- test/q_usd_tiered_sto.js | 12 +++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 8073ab360..3793edc7a 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -82,9 +82,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // List of accredited investors mapping (address => bool) public accredited; - // Limit in USD for non-accredited investors multiplied by 10**18 + // Default limit in USD for non-accredited investors multiplied by 10**18 uint256 public nonAccreditedLimitUSD; + // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 + mapping (address => uint256) public nonAccreditedLimitUSDOverride; + // Minimum investable amount in USD uint256 public minimumInvestmentUSD; @@ -102,6 +105,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { //////////// event SetAllowBeneficialInvestments(bool _allowed); + event SetNonAccreditedLimit(address _investor, uint256 _limit); + event SetAccredited(address _investor, bool _accredited); event TokenPurchase(address indexed _purchaser, address indexed _beneficiary, uint256 _tokens, uint256 _usdAmount, uint256 _tierPrice, uint8 _tier); event FundsReceivedETH(address indexed _purchaser, address indexed _beneficiary, uint256 _usdAmount, uint256 _receivedValue, uint256 _spentValue, uint256 _rate); event FundsReceivedPOLY(address indexed _purchaser, address indexed _beneficiary, uint256 _usdAmount, uint256 _receivedValue, uint256 _spentValue, uint256 _rate); @@ -331,6 +336,22 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_investors.length == _accredited.length); for (uint256 i = 0; i < _investors.length; i++) { accredited[_investors[i]] = _accredited[i]; + emit SetAccredited(_investors[i], _accredited[i]); + } + } + + /** + * @notice Modify the list of overrides for non-accredited limits in USD + * @param _investors Array of investor addresses to modify + * @param _nonAccreditedLimit Array of uints specifying non-accredited limits + */ + function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) public onlyOwner { + //nonAccreditedLimitUSDOverride + require(_investors.length == _nonAccreditedLimit.length); + for (uint256 i = 0; i < _investors.length; i++) { + require(_nonAccreditedLimit[i] > 0, "Limit cannot be 0"); + nonAccreditedLimitUSDOverride[_investors[i]] = _nonAccreditedLimit[i]; + emit SetNonAccreditedLimit(_investors[i], _nonAccreditedLimit[i]); } } @@ -409,9 +430,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Check for non-accredited cap if (!accredited[_beneficiary]) { - require(investorInvestedUSD[_beneficiary] < nonAccreditedLimitUSD, "Non-accredited investor has already reached nonAccreditedLimitUSD"); - if (investedUSD.add(investorInvestedUSD[_beneficiary]) > nonAccreditedLimitUSD) - investedUSD = nonAccreditedLimitUSD.sub(investorInvestedUSD[_beneficiary]); + uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; + require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Non-accredited investor has already reached nonAccreditedLimitUSD"); + if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) + investedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } uint256 spentUSD; diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 72055a32f..137773725 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -122,10 +122,10 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _expiryTime is the time until which the transfer is allowed */ function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - //Passing a _expiryTime == 0 into this function, is equivalent to removing the manual approval. require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); + require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); emit LogAddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); } @@ -137,10 +137,10 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _expiryTime is the time until which the transfer is blocked */ function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - //Passing a _expiryTime == 0 into this function, is equivalent to removing the manual blocking. require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); + require(manualApprovals[_from][_to].expiryTime == 0, "Blocking already exists"); manualBlockings[_from][_to] = ManualBlocking(_expiryTime); emit LogAddManualBlocking(_from, _to, _expiryTime, msg.sender); } diff --git a/test/q_usd_tiered_sto.js b/test/q_usd_tiered_sto.js index 2e179db51..749a99913 100644 --- a/test/q_usd_tiered_sto.js +++ b/test/q_usd_tiered_sto.js @@ -1563,11 +1563,19 @@ contract('USDTieredSTO', accounts => { assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedPOLY.call(ACCREDITED1)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); }); + it("should successfully modify NONACCREDITED cap for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber()); + await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], {from: ISSUER}); + console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); + }); + it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { let stoId = 0; let tierId = 0; - let investment_USD = _nonAccreditedLimitUSD[stoId]; + let investment_USD = (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1));//_nonAccreditedLimitUSD[stoId]; let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); @@ -1577,6 +1585,8 @@ contract('USDTieredSTO', accounts => { let refund_ETH = await convert(stoId, tierId, false, "USD", "ETH", refund_USD); let refund_POLY = await convert(stoId, tierId, false, "USD", "POLY", refund_USD); + console.log("Expected refund in tokens: " + refund_Token.toNumber()); + let snap = await takeSnapshot(); let init_TokenSupply = await I_SecurityToken.totalSupply();