Skip to content

Port dividend fix #610

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

Merged
merged 11 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity ^0.5.0;

import "../STO.sol";
import "../../../interfaces/ISecurityToken.sol";
import "../../modules/STO/STO.sol";
import "../../interfaces/ISecurityToken.sol";
import "./DummySTOStorage.sol";

/**
Expand Down Expand Up @@ -81,4 +81,8 @@ contract DummySTO is DummySTOStorage, STO {
return allPermissions;
}

function () external payable {
//Payable fallback function to allow us to test leaking ETH
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pragma solidity ^0.5.0;

import "../../UpgradableModuleFactory.sol";
import "../../../libraries/Util.sol";
import "../../modules/UpgradableModuleFactory.sol";
import "../../libraries/Util.sol";
import "./DummySTOProxy.sol";
import "../../../interfaces/IBoot.sol";
import "../../interfaces/IBoot.sol";

/**
* @title Factory for deploying DummySTO module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pragma solidity ^0.5.0;

import "../../../proxy/OwnedUpgradeabilityProxy.sol";
import "../../../Pausable.sol";
import "../../proxy/OwnedUpgradeabilityProxy.sol";
import "../../Pausable.sol";
import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol";
import "../../../storage/modules/STO/STOStorage.sol";
import "../../../storage/modules/ModuleStorage.sol";
import "../../storage/modules/STO/STOStorage.sol";
import "../../storage/modules/ModuleStorage.sol";
import "./DummySTOStorage.sol";

/**
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/MockFactory.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma solidity ^0.5.0;

import "../modules/STO/Dummy/DummySTOFactory.sol";
import "./Dummy/DummySTOFactory.sol";

/**
* @title Mock Contract Not fit for production environment
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/TestSTOFactory.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma solidity ^0.5.0;

import "../modules/STO/Dummy/DummySTOFactory.sol";
import "./Dummy/DummySTOFactory.sol";

contract TestSTOFactory is DummySTOFactory {
/**
Expand Down
23 changes: 22 additions & 1 deletion contracts/modules/Checkpoint/DividendCheckpoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module {
event SetWithholding(address[] _investors, uint256[] _withholding);
event SetWithholdingFixed(address[] _investors, uint256 _withholding);
event SetWallet(address indexed _oldWallet, address indexed _newWallet);
event UpdateDividendDates(uint256 indexed _dividendIndex, uint256 _maturity, uint256 _expiry);

function _validDividendIndex(uint256 _dividendIndex) internal view {
require(_dividendIndex < dividends.length, "Invalid dividend");
Expand Down Expand Up @@ -195,7 +196,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module {
* @notice Investors can pull their own dividends
* @param _dividendIndex Dividend to pull
*/
function pullDividendPayment(uint256 _dividendIndex) public {
function pullDividendPayment(uint256 _dividendIndex) public whenNotPaused {
_validDividendIndex(_dividendIndex);
Dividend storage dividend = dividends[_dividendIndex];
require(!dividend.claimed[msg.sender], "Dividend already claimed");
Expand Down Expand Up @@ -265,6 +266,26 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module {
*/
function withdrawWithholding(uint256 _dividendIndex) external;

/**
* @notice Allows issuer to change maturity / expiry dates for dividends
* @dev NB - setting the maturity of a currently matured dividend to a future date
* @dev will effectively refreeze claims on that dividend until the new maturity date passes
* @ dev NB - setting the expiry date to a past date will mean no more payments can be pulled
* @dev or pushed out of a dividend
* @param _dividendIndex Dividend to withdraw from
* @param _maturity updated maturity date
* @param _expiry updated expiry date
*/
function updateDividendDates(uint256 _dividendIndex, uint256 _maturity, uint256 _expiry) external withPerm(ADMIN) {
require(_dividendIndex < dividends.length, "Invalid dividend");
require(_expiry > _maturity, "Expiry before maturity");
Dividend storage dividend = dividends[_dividendIndex];
require(dividend.expiry > now, "Dividend already expired");
dividend.expiry = _expiry;
dividend.maturity = _maturity;
emit UpdateDividendDates(_dividendIndex, _maturity, _expiry);
}

/**
* @notice Get static dividend data
* @return uint256[] timestamp of dividends creation
Expand Down
10 changes: 5 additions & 5 deletions contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,12 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec
uint256 claimAfterWithheld = claim.sub(withheld);
if (claimAfterWithheld > 0) {
require(IERC20(dividendTokens[_dividendIndex]).transfer(_payee, claimAfterWithheld), "transfer failed");
if (withheld > 0) {
_dividend.totalWithheld = _dividend.totalWithheld.add(withheld);
_dividend.withheld[_payee] = withheld;
}
emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld);
}
if (withheld > 0) {
_dividend.totalWithheld = _dividend.totalWithheld.add(withheld);
_dividend.withheld[_payee] = withheld;
}
emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld);
}

/**
Expand Down
22 changes: 10 additions & 12 deletions contracts/modules/Checkpoint/Ether/EtherDividendCheckpoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,17 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
(uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee);
_dividend.claimed[_payee] = true;
uint256 claimAfterWithheld = claim.sub(withheld);
if (claimAfterWithheld > 0) {
/*solium-disable-next-line security/no-send*/
if (_payee.send(claimAfterWithheld)) {
_dividend.claimedAmount = _dividend.claimedAmount.add(claim);
if (withheld > 0) {
_dividend.totalWithheld = _dividend.totalWithheld.add(withheld);
_dividend.withheld[_payee] = withheld;
}
emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld);
} else {
_dividend.claimed[_payee] = false;
emit EtherDividendClaimFailed(_payee, _dividendIndex, claim, withheld);
/*solium-disable-next-line security/no-send*/
if (_payee.send(claimAfterWithheld)) {
_dividend.claimedAmount = _dividend.claimedAmount.add(claim);
if (withheld > 0) {
_dividend.totalWithheld = _dividend.totalWithheld.add(withheld);
_dividend.withheld[_payee] = withheld;
}
emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld);
} else {
_dividend.claimed[_payee] = false;
emit EtherDividendClaimFailed(_payee, _dividendIndex, claim, withheld);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, Wallet {
/**
* @notice Used to withdraw available tokens by beneficiary
*/
function pullAvailableTokens() external {
function pullAvailableTokens() external whenNotPaused {
_sendTokens(msg.sender);
}

Expand Down
12 changes: 1 addition & 11 deletions contracts/modules/Experimental/Wallet/Wallet.sol
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
pragma solidity ^0.5.0;

import "../../../Pausable.sol";
import "../../Module.sol";

/**
* @title Interface to be implemented by all Wallet modules
* @dev abstract contract
*/
contract Wallet is Module, Pausable {
contract Wallet is Module {

function unpause() public {
_onlySecurityTokenOwner();
super._unpause();
}

function pause() public {
_onlySecurityTokenOwner();
super._pause();
}
}
41 changes: 40 additions & 1 deletion contracts/modules/Module.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pragma solidity ^0.5.0;

import "../interfaces/IModule.sol";
import "../Pausable.sol";
import "../interfaces/IModuleFactory.sol";
import "../interfaces/IDataStore.sol";
import "../interfaces/ISecurityToken.sol";
Expand All @@ -13,7 +14,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
* @title Interface that any module contract should implement
* @notice Contract is abstract
*/
contract Module is IModule, ModuleStorage {
contract Module is IModule, ModuleStorage, Pausable {
/**
* @notice Constructor
* @param _securityToken Address of the security token
Expand Down Expand Up @@ -54,6 +55,22 @@ contract Module is IModule, ModuleStorage {
_;
}

/**
* @notice Pause (overridden function)
*/
function pause() public {
_onlySecurityTokenOwner();
super._pause();
}

/**
* @notice Unpause (overridden function)
*/
function unpause() public {
_onlySecurityTokenOwner();
super._unpause();
}

/**
* @notice used to withdraw the fee by the factory owner
*/
Expand All @@ -68,4 +85,26 @@ contract Module is IModule, ModuleStorage {
function getDataStore() public view returns(IDataStore) {
return IDataStore(ISecurityToken(securityToken).dataStore());
}

/**
* @notice Reclaims ERC20Basic compatible tokens
* @dev We duplicate here due to the overriden owner & onlyOwner
* @param _tokenContract The address of the token contract
*/
function reclaimERC20(address _tokenContract) external {
_onlySecurityTokenOwner();
require(_tokenContract != address(0), "Invalid address");
IERC20 token = IERC20(_tokenContract);
uint256 balance = token.balanceOf(address(this));
require(token.transfer(msg.sender, balance), "Transfer failed");
}

/**
* @notice Reclaims ETH
* @dev We duplicate here due to the overriden owner & onlyOwner
*/
function reclaimETH() external {
_onlySecurityTokenOwner();
msg.sender.transfer(address(this).balance);
}
}
6 changes: 2 additions & 4 deletions contracts/modules/STO/Capped/CappedSTO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,11 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard {
* @notice Low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) public payable nonReentrant {
function buyTokens(address _beneficiary) public payable whenNotPaused nonReentrant {
if (!allowBeneficialInvestments) {
require(_beneficiary == msg.sender, "Beneficiary address does not match msg.sender");
}

require(!paused, "Should not be paused");
require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "Mode of investment is not ETH");

uint256 weiAmount = msg.value;
Expand All @@ -110,8 +109,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard {
* @notice low level token purchase
* @param _investedPOLY Amount of POLY invested
*/
function buyTokensWithPoly(uint256 _investedPOLY) public nonReentrant {
require(!paused, "Should not be paused");
function buyTokensWithPoly(uint256 _investedPOLY) public whenNotPaused nonReentrant {
require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY");
uint256 refund = _processTx(msg.sender, _investedPOLY);
_forwardPoly(msg.sender, wallet, _investedPOLY.sub(refund));
Expand Down
28 changes: 3 additions & 25 deletions contracts/modules/STO/STO.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pragma solidity ^0.5.0;

import "../../Pausable.sol";
import "../Module.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../../storage/modules/STO/STOStorage.sol";
Expand All @@ -10,27 +9,14 @@ import "../../interfaces/ISTO.sol";
/**
* @title Base abstract contract to be extended by all STO modules
*/
contract STO is ISTO, STOStorage, Module, Pausable {
contract STO is ISTO, STOStorage, Module {
using SafeMath for uint256;

enum FundRaiseType {ETH, POLY, SC}

// Event
event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes);

/**
* @notice Reclaims ERC20Basic compatible tokens
* @dev We duplicate here due to the overriden owner & onlyOwner
* @param _tokenContract The address of the token contract
*/
function reclaimERC20(address _tokenContract) external {
_onlySecurityTokenOwner();
require(_tokenContract != address(0), "Invalid address");
IERC20 token = IERC20(_tokenContract);
uint256 balance = token.balanceOf(address(this));
require(token.transfer(msg.sender, balance), "Transfer failed");
}

/**
* @notice Returns funds raised by the STO
*/
Expand All @@ -45,20 +31,12 @@ contract STO is ISTO, STOStorage, Module, Pausable {

/**
* @notice Pause (overridden function)
* @dev Only securityToken owner restriction applied on the super function
*/
function pause() public {
_onlySecurityTokenOwner();
/*solium-disable-next-line security/no-block-members*/
require(now < endTime, "STO has been finalized");
super._pause();
}

/**
* @notice Unpause (overridden function)
*/
function unpause() public {
_onlySecurityTokenOwner();
super._unpause();
super.pause();
}

function _setFundRaiseType(FundRaiseType[] memory _fundRaiseTypes) internal {
Expand Down
6 changes: 3 additions & 3 deletions contracts/modules/STO/USDTiered/USDTieredSTO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO {
*/
function finalize() external {
_onlySecurityTokenOwner();
require(!isFinalized, "STO already finalized");
require(!isFinalized, "STO is finalized");
isFinalized = true;
uint256 tempReturned;
uint256 tempSold;
Expand Down Expand Up @@ -322,7 +322,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO {
*/
function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) external {
_onlySecurityTokenOwner();
require(_allowBeneficialInvestments != allowBeneficialInvestments, "Value unchanged");
require(_allowBeneficialInvestments != allowBeneficialInvestments);
allowBeneficialInvestments = _allowBeneficialInvestments;
emit SetAllowBeneficialInvestments(allowBeneficialInvestments);
}
Expand Down Expand Up @@ -409,7 +409,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO {
initialMinted = getTokensMinted();
rate = getRate(_fundRaiseType);
(spentUSD, spentValue) = _buyTokens(_beneficiary, _amount, rate, _fundRaiseType);
require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient tokens minted");
require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient minted");
}


Expand Down
12 changes: 1 addition & 11 deletions contracts/modules/TransferManager/TransferManager.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
pragma solidity ^0.5.0;

import "../../Pausable.sol";
import "../Module.sol";
import "../../interfaces/ITransferManager.sol";

/**
* @title Base abstract contract to be implemented by all Transfer Manager modules
*/
contract TransferManager is ITransferManager, Module, Pausable {
contract TransferManager is ITransferManager, Module {

bytes32 public constant LOCKED = "LOCKED";
bytes32 public constant UNLOCKED = "UNLOCKED";
Expand All @@ -17,13 +16,4 @@ contract TransferManager is ITransferManager, Module, Pausable {
_;
}

function unpause() public {
_onlySecurityTokenOwner();
super._unpause();
}

function pause() public {
_onlySecurityTokenOwner();
super._pause();
}
}
Loading