@@ -3,15 +3,15 @@ pragma solidity 0.8.4;
33
44import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol " ;
55import "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
6- import "@openzeppelin/ contracts/access/Ownable .sol " ;
6+ import "contracts/utils/Whitelist .sol " ;
77
88/**
99 * @title Automatic Private sale
1010 * @author Michael Araque
1111 * @notice A contract that manages a Public Private Sale, purchase, claiming and vesting time
1212 */
1313
14- contract FoxtrotPrivateSale is Ownable {
14+ contract FoxtrotPrivateSale is Whitelist {
1515 enum InvestorTrace {
1616 CLAIMED,
1717 LOCKED,
@@ -30,40 +30,46 @@ contract FoxtrotPrivateSale is Ownable {
3030 mapping (address => mapping (InvestorTrace => uint256 )) private accounting;
3131 mapping (ContractDates => uint256 ) private dates;
3232
33+ event UpdatePrivateSaleStatus (bool isOpen );
3334 event ClaimToken (address tokenAddress , uint256 tokenAmount );
3435 event Invest (address investor , uint256 busdAmount , uint256 tokenAmount );
3536
3637 address public busdContract;
3738 address public tokenContract;
3839 address public companyVault;
3940
41+ bool public isPrivateSaleOpen;
4042 bool public isClaimEnabled;
4143 uint256 private tokensSoldCounter;
4244 uint256 public totalBusdInvested;
4345
4446 uint256 private immutable TGE_PERCENT = 8 ;
4547 uint256 private immutable AFTER_TGE_BLOCK_TIME = 90 days ;
46- uint256 private immutable FXD_PRICE = 30000000000000000 wei ;
47- uint256 private immutable MIN_BUSD_ACCEPTED = 50 ether ;
48- uint256 private constant MAX_AMOUNT_TOKEN = 15050000 ether ;
48+ uint256 private immutable FXD_PRICE = 25000000000000000 wei ;
49+ uint256 private immutable MIN_BUSD_ACCEPTED = 1 ether ;
50+ uint256 private constant MAX_AMOUNT_TOKEN = 32_250_000 ether ;
4951
5052 constructor (address _companyVault , address _busdContract ) {
5153 companyVault = _companyVault;
5254 busdContract = _busdContract;
5355 tokenContract = address (0 );
56+ Whitelist.isWhitelistEnabled = true ;
5457
5558 tokensSoldCounter = MAX_AMOUNT_TOKEN;
5659
5760 dates[ContractDates.SALE_START] = 1665504776 ;
58- dates[ContractDates.SALE_END] = 1728663176 ;
5961 dates[ContractDates.VESTING_PERIOD] = 360 days ;
62+
63+ isPrivateSaleOpen = true ;
6064 }
6165
6266 /**
6367 * @dev This function allows to invest in the private sale
6468 * @param amount Amount in BUSD to be invested in wei format
6569 */
66- function invest (uint256 amount ) public {
70+ function invest (uint256 amount ) public onlyWhitelisted {
71+ require (isPrivateSaleOpen, "FXD: Private Sale is closed " );
72+
6773 require (
6874 IERC20 (busdContract).balanceOf (msg .sender ) >= amount,
6975 "FXD: Insufficient BUSD "
@@ -74,15 +80,23 @@ contract FoxtrotPrivateSale is Ownable {
7480 );
7581 require (
7682 block .timestamp >= dates[ContractDates.SALE_START],
77- "FXD: Private Sale not started "
78- );
79- require (
80- block .timestamp <= dates[ContractDates.SALE_END],
81- "FXD: Private Sale ended "
83+ "FXD: Private Sale not started yet "
8284 );
8385
86+ if (Whitelist.isWhitelistEnabled) {
87+ require (
88+ accounting[msg .sender ][InvestorTrace.BUSD_INVESTED] <=
89+ Whitelist.amount[msg .sender ] &&
90+ amount <= Whitelist.amount[msg .sender ] &&
91+ accounting[msg .sender ][InvestorTrace.BUSD_INVESTED] +
92+ amount <=
93+ Whitelist.amount[msg .sender ],
94+ "FXD: Private Sale purchase limit "
95+ );
96+ }
97+
8498 if (tokensSoldCounter >= getTokenAmount (MIN_BUSD_ACCEPTED, FXD_PRICE))
85- require (amount >= MIN_BUSD_ACCEPTED, "FXD: Minimum amount 50 BUSD " );
99+ require (amount >= MIN_BUSD_ACCEPTED, "FXD: Minimum amount 1 BUSD " );
86100
87101 uint256 tokensAmount = getTokenAmount (amount, FXD_PRICE);
88102 require (
@@ -134,7 +148,7 @@ contract FoxtrotPrivateSale is Ownable {
134148 * @dev ClaimToken Emit event
135149 * @notice This method is the main method to claim tokens
136150 */
137- function claim () external {
151+ function claim () external onlyWhitelisted {
138152 require (isClaimEnabled, "FXD: Claim status inactive " );
139153 require (
140154 accounting[msg .sender ][InvestorTrace.LOCKED] > 0 ,
@@ -328,7 +342,7 @@ contract FoxtrotPrivateSale is Ownable {
328342 * @param from Address of the investor
329343 * @return uint256 Returns the total amount of tokens that the investor has invested
330344 */
331- function historicalBalance (address from ) internal view returns (uint256 ) {
345+ function historicalBalance (address from ) external view returns (uint256 ) {
332346 return (accounting[from][InvestorTrace.LOCKED] +
333347 accounting[from][InvestorTrace.CLAIMED]);
334348 }
@@ -347,18 +361,26 @@ contract FoxtrotPrivateSale is Ownable {
347361 }
348362
349363 /**
350- * @notice This method is a helper function that allows to set the end of the sale manually
364+ * @notice This method is a helper function that allows to close the private sale manually
351365 */
352- function setSaleEnd () external onlyOwner returns ( bool ) {
353- dates[ContractDates.SALE_END] = block . timestamp ;
354- return true ;
366+ function setSaleEnd () external onlyOwner {
367+ isPrivateSaleOpen = false ;
368+ emit UpdatePrivateSaleStatus ( false ) ;
355369 }
356370
357371 /**
358- * @return uint256 Date of the Private sale end
372+ * @notice This method is a helper function that allows to open the private sale manually
359373 */
360- function getSaleEnd () external view returns (uint256 ) {
361- return dates[ContractDates.SALE_END];
374+ function openPrivateSale () external onlyOwner {
375+ isPrivateSaleOpen = true ;
376+ emit UpdatePrivateSaleStatus (true );
377+ }
378+
379+ /**
380+ * @return bool Show is the privatesale is open or closed
381+ */
382+ function showPrivateSaleStatus () external view returns (bool ) {
383+ return isPrivateSaleOpen;
362384 }
363385
364386 /**
@@ -398,7 +420,10 @@ contract FoxtrotPrivateSale is Ownable {
398420 "FXD: You can't withdraw Foxtrot Tokens "
399421 );
400422 IERC20 Token = IERC20 (token);
401- require (Token.balanceOf (address (this )) >= amount, "FXD: Insufficient amount " );
423+ require (
424+ Token.balanceOf (address (this )) >= amount,
425+ "FXD: Insufficient amount "
426+ );
402427 Token.transfer (receiver, amount);
403428 return true ;
404429 }
@@ -408,10 +433,6 @@ contract FoxtrotPrivateSale is Ownable {
408433 * to the Foxtrot Command (FXD) Contract
409434 */
410435 function purgeNonSelledTokens () external onlyOwner {
411- require (
412- block .timestamp >= dates[ContractDates.SALE_END],
413- "FXD: Private sale is still alive "
414- );
415436 SafeERC20.safeTransfer (
416437 IERC20 (tokenContract),
417438 tokenContract,
0 commit comments