Skip to content

Commit fd51e7a

Browse files
maxsam4adamdossa
authored andcommitted
STO fixes (#583)
* Minor STO changes * typo fix * Added STO interface * Typo fixed * Refund remaining amount in last cappedsto tx
1 parent 9062fdf commit fd51e7a

File tree

10 files changed

+57
-71
lines changed

10 files changed

+57
-71
lines changed

contracts/interfaces/ISTO.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
pragma solidity ^0.4.24;
2+
3+
/**
4+
* @title Interface to be implemented by all STO modules
5+
*/
6+
interface ISTO {
7+
/**
8+
* @notice Returns the total no. of tokens sold
9+
*/
10+
function getTokensSold() external view returns (uint256);
11+
}

contracts/modules/STO/CappedSTO.sol

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
pragma solidity ^0.4.24;
22

3-
import "./ISTO.sol";
3+
import "./STO.sol";
44
import "../../interfaces/ISecurityToken.sol";
55
import "openzeppelin-solidity/contracts/ReentrancyGuard.sol";
66
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
77

88
/**
99
* @title STO module for standard capped crowdsale
1010
*/
11-
contract CappedSTO is ISTO, ReentrancyGuard {
11+
contract CappedSTO is STO, ReentrancyGuard {
1212
using SafeMath for uint256;
1313

1414
// Determine whether users can invest on behalf of a beneficiary
@@ -51,7 +51,7 @@ contract CappedSTO is ISTO, ReentrancyGuard {
5151
* @param _startTime Unix timestamp at which offering get started
5252
* @param _endTime Unix timestamp at which offering get ended
5353
* @param _cap Maximum No. of token base units for sale
54-
* @param _rate Token units a buyer gets multiplied by 10^18 per wei / base unit of POLY
54+
* @param _rate Token units a buyer gets multiplied by 10^18 per wei / base unit of POLY
5555
* @param _fundRaiseTypes Type of currency used to collect the funds
5656
* @param _fundsReceiver Ethereum account address to hold the funds
5757
*/
@@ -115,7 +115,6 @@ contract CappedSTO is ISTO, ReentrancyGuard {
115115
weiAmount = weiAmount.sub(refund);
116116

117117
_forwardFunds(refund);
118-
_postValidatePurchase(_beneficiary, weiAmount);
119118
}
120119

121120
/**
@@ -127,7 +126,6 @@ contract CappedSTO is ISTO, ReentrancyGuard {
127126
require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY");
128127
uint256 refund = _processTx(msg.sender, _investedPOLY);
129128
_forwardPoly(msg.sender, wallet, _investedPOLY.sub(refund));
130-
_postValidatePurchase(msg.sender, _investedPOLY.sub(refund));
131129
}
132130

133131
/**
@@ -161,7 +159,7 @@ contract CappedSTO is ISTO, ReentrancyGuard {
161159
* @return Token units a buyer gets(multiplied by 10^18) per wei / base unit of POLY
162160
* @return Amount of funds raised
163161
* @return Number of individual investors this STO have.
164-
* @return Amount of tokens get sold.
162+
* @return Amount of tokens get sold.
165163
* @return Boolean value to justify whether the fund raise type is POLY or not, i.e true for POLY.
166164
*/
167165
function getSTODetails() public view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool) {
@@ -203,8 +201,6 @@ contract CappedSTO is ISTO, ReentrancyGuard {
203201

204202
_processPurchase(_beneficiary, tokens);
205203
emit TokenPurchase(msg.sender, _beneficiary, _investedAmount, tokens);
206-
207-
_updatePurchasingState(_beneficiary, _investedAmount);
208204
}
209205

210206
/**
@@ -216,21 +212,10 @@ contract CappedSTO is ISTO, ReentrancyGuard {
216212
function _preValidatePurchase(address _beneficiary, uint256 _investedAmount) internal view {
217213
require(_beneficiary != address(0), "Beneficiary address should not be 0x");
218214
require(_investedAmount != 0, "Amount invested should not be equal to 0");
219-
uint256 tokens;
220-
(tokens, ) = _getTokenAmount(_investedAmount);
221-
require(totalTokensSold.add(tokens) <= cap, "Investment more than cap is not allowed");
222215
/*solium-disable-next-line security/no-block-members*/
223216
require(now >= startTime && now <= endTime, "Offering is closed/Not yet started");
224217
}
225218

226-
/**
227-
* @notice Validation of an executed purchase.
228-
Observe state and use revert statements to undo rollback when valid conditions are not met.
229-
*/
230-
function _postValidatePurchase(address /*_beneficiary*/, uint256 /*_investedAmount*/) internal pure {
231-
// optional override
232-
}
233-
234219
/**
235220
* @notice Source of tokens.
236221
Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
@@ -255,27 +240,23 @@ contract CappedSTO is ISTO, ReentrancyGuard {
255240
_deliverTokens(_beneficiary, _tokenAmount);
256241
}
257242

258-
/**
259-
* @notice Overrides for extensions that require an internal state to check for validity
260-
(current user contributions, etc.)
261-
*/
262-
function _updatePurchasingState(address /*_beneficiary*/, uint256 /*_investedAmount*/) internal pure {
263-
// optional override
264-
}
265-
266243
/**
267244
* @notice Overrides to extend the way in which ether is converted to tokens.
268245
* @param _investedAmount Value in wei to be converted into tokens
269246
* @return Number of tokens that can be purchased with the specified _investedAmount
270247
* @return Remaining amount that should be refunded to the investor
271248
*/
272-
function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 _tokens, uint256 _refund) {
273-
_tokens = _investedAmount.mul(rate);
274-
_tokens = _tokens.div(uint256(10) ** 18);
249+
function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 tokens, uint256 refund) {
250+
tokens = _investedAmount.mul(rate);
251+
tokens = tokens.div(uint256(10) ** 18);
252+
if (totalTokensSold.add(tokens) > cap) {
253+
tokens = cap.sub(totalTokensSold);
254+
}
275255
uint256 granularity = ISecurityToken(securityToken).granularity();
276-
_tokens = _tokens.div(granularity);
277-
_tokens = _tokens.mul(granularity);
278-
_refund = _investedAmount.sub((_tokens.mul(uint256(10) ** 18)).div(rate));
256+
tokens = tokens.div(granularity);
257+
tokens = tokens.mul(granularity);
258+
require(tokens > 0, "Cap reached");
259+
refund = _investedAmount.sub((tokens.mul(uint256(10) ** 18)).div(rate));
279260
}
280261

281262
/**

contracts/modules/STO/DummySTO.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
pragma solidity ^0.4.24;
22

3-
import "./ISTO.sol";
3+
import "./STO.sol";
44
import "../../interfaces/ISecurityToken.sol";
55

66
/**
77
* @title STO module for sample implementation of a different crowdsale module
88
*/
9-
contract DummySTO is ISTO {
9+
contract DummySTO is STO {
1010

1111
bytes32 public constant ADMIN = "ADMIN";
1212

contracts/modules/STO/PreSaleSTO.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
pragma solidity ^0.4.24;
22

3-
import "./ISTO.sol";
3+
import "./STO.sol";
44
import "../../interfaces/ISecurityToken.sol";
55
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
66

77
/**
88
* @title STO module for private presales
99
*/
10-
contract PreSaleSTO is ISTO {
10+
contract PreSaleSTO is STO {
1111
using SafeMath for uint256;
1212

1313
bytes32 public constant PRE_SALE_ADMIN = "PRE_SALE_ADMIN";
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ pragma solidity ^0.4.24;
33
import "../../Pausable.sol";
44
import "../Module.sol";
55
import "../../interfaces/IERC20.sol";
6-
import "./ISTOStorage.sol";
6+
import "../../interfaces/ISTO.sol";
7+
import "./STOStorage.sol";
78
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
89

910
/**
1011
* @title Interface to be implemented by all STO modules
1112
*/
12-
contract ISTO is ISTOStorage, Module, Pausable {
13+
contract STO is ISTO, STOStorage, Module, Pausable {
1314
using SafeMath for uint256;
1415

1516
enum FundRaiseType { ETH, POLY, SC }
16-
17+
1718
// Event
1819
event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes);
1920

@@ -36,11 +37,6 @@ contract ISTO is ISTOStorage, Module, Pausable {
3637
return fundsRaised[uint8(_fundRaiseType)];
3738
}
3839

39-
/**
40-
* @notice Returns the total no. of tokens sold
41-
*/
42-
function getTokensSold() public view returns (uint256);
43-
4440
/**
4541
* @notice Pause (overridden function)
4642
*/
@@ -59,7 +55,7 @@ contract ISTO is ISTOStorage, Module, Pausable {
5955

6056
function _setFundRaiseType(FundRaiseType[] _fundRaiseTypes) internal {
6157
// FundRaiseType[] parameter type ensures only valid values for _fundRaiseTypes
62-
require(_fundRaiseTypes.length > 0, "Raise type is not specified");
58+
require(_fundRaiseTypes.length > 0 && _fundRaiseTypes.length <= 3, "Raise type is not specified");
6359
fundRaiseTypes[uint8(FundRaiseType.ETH)] = false;
6460
fundRaiseTypes[uint8(FundRaiseType.POLY)] = false;
6561
fundRaiseTypes[uint8(FundRaiseType.SC)] = false;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
pragma solidity ^0.4.24;
22

33
/**
4-
* @title Storage layout for the ISTO contract
4+
* @title Storage layout for the STO contract
55
*/
6-
contract ISTOStorage {
6+
contract STOStorage {
77

88
mapping (uint8 => bool) public fundRaiseTypes;
99
mapping (uint8 => uint256) public fundsRaised;
@@ -21,4 +21,4 @@ contract ISTOStorage {
2121
// Final amount of tokens sold
2222
uint256 public totalTokensSold;
2323

24-
}
24+
}

contracts/modules/STO/USDTieredSTO.sol

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pragma solidity ^0.4.24;
22

3-
import "./ISTO.sol";
3+
import "./STO.sol";
44
import "../../interfaces/ISecurityToken.sol";
55
import "../../interfaces/IOracle.sol";
66
import "../../RegistryUpdater.sol";
@@ -12,7 +12,7 @@ import "../../storage/USDTieredSTOStorage.sol";
1212
/**
1313
* @title STO module for standard capped crowdsale
1414
*/
15-
contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
15+
contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard {
1616
using SafeMath for uint256;
1717

1818
string public constant POLY_ORACLE = "PolyUsdOracle";
@@ -262,7 +262,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
262262
}
263263
usdTokens = _usdTokens;
264264
for(i = 0; i < _usdTokens.length; i++) {
265-
require(_usdTokens[i] != address(0), "Invalid USD token");
265+
require(_usdTokens[i] != address(0) && _usdTokens[i] != address(polyToken), "Invalid USD token");
266266
usdTokenEnabled[_usdTokens[i]] = true;
267267
}
268268
emit SetAddresses(wallet, reserveWallet, _usdTokens);
@@ -276,7 +276,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
276276
* @notice Finalizes the STO and mint remaining tokens to reserve address
277277
* @notice Reserve address must be whitelisted to successfully finalize
278278
*/
279-
function finalize() public onlyOwner {
279+
function finalize() external onlyOwner {
280280
require(!isFinalized, "STO is already finalized");
281281
isFinalized = true;
282282
uint256 tempReturned;
@@ -301,7 +301,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
301301
* @param _investors Array of investor addresses to modify
302302
* @param _accredited Array of bools specifying accreditation status
303303
*/
304-
function changeAccredited(address[] _investors, bool[] _accredited) public onlyOwner {
304+
function changeAccredited(address[] _investors, bool[] _accredited) external onlyOwner {
305305
require(_investors.length == _accredited.length, "Array length mismatch");
306306
for (uint256 i = 0; i < _investors.length; i++) {
307307
if (_accredited[i]) {
@@ -319,7 +319,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
319319
* @param _investors Array of investor addresses to modify
320320
* @param _nonAccreditedLimit Array of uints specifying non-accredited limits
321321
*/
322-
function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) public onlyOwner {
322+
function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) external onlyOwner {
323323
//nonAccreditedLimitUSDOverride
324324
require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch");
325325
for (uint256 i = 0; i < _investors.length; i++) {
@@ -357,7 +357,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
357357
* @notice Function to set allowBeneficialInvestments (allow beneficiary to be different to funder)
358358
* @param _allowBeneficialInvestments Boolean to allow or disallow beneficial investments
359359
*/
360-
function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) public onlyOwner {
360+
function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) external onlyOwner {
361361
require(_allowBeneficialInvestments != allowBeneficialInvestments, "Value unchanged");
362362
allowBeneficialInvestments = _allowBeneficialInvestments;
363363
emit SetAllowBeneficialInvestments(allowBeneficialInvestments);
@@ -508,7 +508,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
508508
uint256 _investmentValue,
509509
FundRaiseType _fundRaiseType
510510
)
511-
public
511+
external
512512
view
513513
returns(uint256 spentUSD, uint256 spentValue, uint256 tokensMinted)
514514
{
@@ -732,7 +732,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
732732
* @param _amount Value to convert to USD
733733
* @return uint256 Value in USD
734734
*/
735-
function convertToUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) {
735+
function convertToUSD(FundRaiseType _fundRaiseType, uint256 _amount) external view returns(uint256) {
736736
uint256 rate = getRate(_fundRaiseType);
737737
return DecimalMath.mul(_amount, rate);
738738
}
@@ -743,7 +743,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
743743
* @param _amount Value to convert from USD
744744
* @return uint256 Value in ETH or POLY
745745
*/
746-
function convertFromUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) {
746+
function convertFromUSD(FundRaiseType _fundRaiseType, uint256 _amount) external view returns(uint256) {
747747
uint256 rate = getRate(_fundRaiseType);
748748
return DecimalMath.div(_amount, rate);
749749
}
@@ -776,7 +776,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
776776
* param _fundRaiseType The fund raising currency (e.g. ETH, POLY, SC) to calculate sold tokens for
777777
* @return uint256 Total number of tokens sold for ETH
778778
*/
779-
function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns (uint256) {
779+
function getTokensSoldFor(FundRaiseType _fundRaiseType) external view returns (uint256) {
780780
uint256 tokensSold;
781781
for (uint256 i = 0; i < tiers.length; i++) {
782782
tokensSold = tokensSold.add(tiers[i].minted[uint8(_fundRaiseType)]);
@@ -789,7 +789,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
789789
* param _tier The tier to return minted tokens for
790790
* @return uint256[] array of minted tokens in each fund raise type
791791
*/
792-
function getTokensMintedByTier(uint256 _tier) public view returns (uint256[]) {
792+
function getTokensMintedByTier(uint256 _tier) external view returns (uint256[]) {
793793
require(_tier < tiers.length, "Invalid tier");
794794
uint256[] memory tokensMinted = new uint256[](3);
795795
tokensMinted[0] = tiers[_tier].minted[uint8(FundRaiseType.ETH)];
@@ -803,7 +803,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
803803
* param _tier The tier to calculate sold tokens for
804804
* @return uint256 Total number of tokens sold in the tier
805805
*/
806-
function getTokensSoldByTier(uint256 _tier) public view returns (uint256) {
806+
function getTokensSoldByTier(uint256 _tier) external view returns (uint256) {
807807
require(_tier < tiers.length, "Incorrect tier");
808808
uint256 tokensSold;
809809
tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.ETH)]);
@@ -816,15 +816,15 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
816816
* @notice Return the total no. of tiers
817817
* @return uint256 Total number of tiers
818818
*/
819-
function getNumberOfTiers() public view returns (uint256) {
819+
function getNumberOfTiers() external view returns (uint256) {
820820
return tiers.length;
821821
}
822822

823823
/**
824824
* @notice Return the usd tokens accepted by the STO
825825
* @return address[] usd tokens
826826
*/
827-
function getUsdTokens() public view returns (address[]) {
827+
function getUsdTokens() external view returns (address[]) {
828828
return usdTokens;
829829
}
830830

@@ -848,7 +848,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard {
848848
* @return Amount of tokens sold.
849849
* @return Array of bools to show if funding is allowed in ETH, POLY, SC respectively
850850
*/
851-
function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) {
851+
function getSTODetails() external view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) {
852852
uint256[] memory cap = new uint256[](tiers.length);
853853
uint256[] memory rate = new uint256[](tiers.length);
854854
for(uint256 i = 0; i < tiers.length; i++) {

contracts/proxy/USDTieredSTOProxy.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import "../storage/USDTieredSTOStorage.sol";
44
import "./OwnedProxy.sol";
55
import "../Pausable.sol";
66
import "openzeppelin-solidity/contracts/ReentrancyGuard.sol";
7-
import "../modules/STO/ISTOStorage.sol";
7+
import "../modules/STO/STOStorage.sol";
88
import "../modules/ModuleStorage.sol";
99

1010
/**
1111
* @title USDTiered STO module Proxy
1212
*/
13-
contract USDTieredSTOProxy is USDTieredSTOStorage, ISTOStorage, ModuleStorage, Pausable, ReentrancyGuard, OwnedProxy {
13+
contract USDTieredSTOProxy is USDTieredSTOStorage, STOStorage, ModuleStorage, Pausable, ReentrancyGuard, OwnedProxy {
1414

1515
/**
1616
* @notice Constructor

contracts/storage/USDTieredSTOStorage.sol

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ contract USDTieredSTOStorage {
5151
// Whether or not the STO has been finalized
5252
bool public isFinalized;
5353

54-
// Address where ETH, POLY & Stable Coin funds are delivered
55-
address public wallet;
56-
5754
// Address of issuer reserve wallet for unsold tokens
5855
address public reserveWallet;
5956

0 commit comments

Comments
 (0)