-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Yaroslav
committed
Feb 25, 2021
1 parent
75ab2ef
commit 2e4aad9
Showing
17 changed files
with
12,251 additions
and
38 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
pragma solidity 0.6.12; | ||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
contract ERC20Decimal is ERC20 { | ||
constructor( uint256 totalSupply, | ||
string memory name, | ||
string memory symbol, | ||
uint8 decimal) public ERC20(name, symbol) { | ||
_setupDecimals(decimal); | ||
_mint(msg.sender, totalSupply); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
pragma solidity 0.6.12; | ||
|
||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/math/SafeMath.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; | ||
import "./IDOPool.sol"; | ||
|
||
contract IDOMaster is Ownable { | ||
using SafeMath for uint256; | ||
using SafeERC20 for ERC20Burnable; | ||
using SafeERC20 for ERC20; | ||
|
||
ERC20Burnable public feeToken; | ||
address public feeWallet; | ||
uint256 public feeAmount; | ||
uint256 public burnPercent; | ||
uint256 public divider; | ||
|
||
event IDOCreated(address owner, address idoPool, | ||
uint256 tokenPrice, | ||
address rewardToken, | ||
uint256 startTimestamp, | ||
uint256 finishTimestamp, | ||
uint256 startClaimTimestamp, | ||
uint256 minEthPayment, | ||
uint256 maxEthPayment, | ||
uint256 maxDistributedTokenAmount); | ||
|
||
event TokenFeeUpdated(address newFeeToken); | ||
event FeeAmountUpdated(uint256 newFeeAmount); | ||
event BurnPercentUpdated(uint256 newBurnPercent, uint256 divider); | ||
event FeeWalletUpdated(address newFeeWallet); | ||
|
||
constructor( | ||
ERC20Burnable _feeToken, | ||
address _feeWallet, | ||
uint256 _feeAmount, | ||
uint256 _burnPercent | ||
) public { | ||
feeToken = _feeToken; | ||
feeAmount = _feeAmount; | ||
feeWallet = _feeWallet; | ||
burnPercent = _burnPercent; | ||
divider = 100; | ||
} | ||
|
||
function setFeeToken(address _newFeeToken) external onlyOwner { | ||
require(isContract(_newFeeToken), "New address is not a token"); | ||
feeToken = ERC20Burnable(_newFeeToken); | ||
|
||
emit TokenFeeUpdated(_newFeeToken); | ||
} | ||
|
||
function setFeeAmount(uint256 _newFeeAmount) external onlyOwner { | ||
feeAmount = _newFeeAmount; | ||
|
||
emit FeeAmountUpdated(_newFeeAmount); | ||
} | ||
|
||
function setFeeWallet(address _newFeeWallet) external onlyOwner { | ||
feeWallet = _newFeeWallet; | ||
|
||
emit FeeWalletUpdated(_newFeeWallet); | ||
} | ||
|
||
function setBurnPercent(uint256 _newBurnPercent, uint256 _newDivider) | ||
external | ||
onlyOwner | ||
{ | ||
require(_newBurnPercent <= _newDivider, "Burn percent must be less than divider"); | ||
burnPercent = _newBurnPercent; | ||
divider = _newDivider; | ||
|
||
emit BurnPercentUpdated(_newBurnPercent, _newDivider); | ||
} | ||
|
||
function createIDO( | ||
uint256 _tokenPrice, | ||
ERC20 _rewardToken, | ||
uint256 _startTimestamp, | ||
uint256 _finishTimestamp, | ||
uint256 _startClaimTimestamp, | ||
uint256 _minEthPayment, | ||
uint256 _maxEthPayment, | ||
uint256 _maxDistributedTokenAmount | ||
) external { | ||
if(feeAmount > 0){ | ||
uint256 burnAmount = feeAmount.mul(burnPercent).div(divider); | ||
|
||
feeToken.safeTransferFrom( | ||
msg.sender, | ||
feeWallet, | ||
feeAmount.sub(burnAmount) | ||
); | ||
feeToken.safeTransferFrom(msg.sender, address(this), burnAmount); | ||
feeToken.burn(burnAmount); | ||
} | ||
IDOPool idoPool = | ||
new IDOPool( | ||
_tokenPrice, | ||
_rewardToken, | ||
_startTimestamp, | ||
_finishTimestamp, | ||
_startClaimTimestamp, | ||
_minEthPayment, | ||
_maxEthPayment, | ||
_maxDistributedTokenAmount | ||
); | ||
idoPool.transferOwnership(msg.sender); | ||
|
||
_rewardToken.safeTransferFrom( | ||
msg.sender, | ||
address(idoPool), | ||
_maxDistributedTokenAmount | ||
); | ||
|
||
emit IDOCreated(msg.sender, | ||
address(idoPool), | ||
_tokenPrice, | ||
address(_rewardToken), | ||
_startTimestamp, | ||
_finishTimestamp, | ||
_startClaimTimestamp, | ||
_minEthPayment, | ||
_maxEthPayment, | ||
_maxDistributedTokenAmount); | ||
} | ||
|
||
function isContract(address _addr) private view returns (bool) { | ||
uint32 size; | ||
assembly { | ||
size := extcodesize(_addr) | ||
} | ||
return (size > 0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
pragma solidity 0.6.12; | ||
|
||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; | ||
import "@openzeppelin/contracts/math/SafeMath.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
contract IDOPool is Ownable, ReentrancyGuard { | ||
using SafeMath for uint256; | ||
using SafeERC20 for ERC20; | ||
|
||
uint256 public tokenPrice; | ||
ERC20 public rewardToken; | ||
uint256 public decimals; | ||
uint256 public startTimestamp; | ||
uint256 public finishTimestamp; | ||
uint256 public startClaimTimestamp; | ||
uint256 public minEthPayment; | ||
uint256 public maxEthPayment; | ||
uint256 public maxDistributedTokenAmount; | ||
uint256 public tokensForDistribution; | ||
uint256 public distributedTokens; | ||
|
||
struct UserInfo { | ||
uint debt; | ||
uint total; | ||
uint totalInvestedETH; | ||
} | ||
|
||
mapping(address => UserInfo) public userInfo; | ||
|
||
event TokensDebt( | ||
address indexed holder, | ||
uint256 ethAmount, | ||
uint256 tokenAmount | ||
); | ||
|
||
event TokensWithdrawn(address indexed holder, uint256 amount); | ||
|
||
constructor( | ||
uint256 _tokenPrice, | ||
ERC20 _rewardToken, | ||
uint256 _startTimestamp, | ||
uint256 _finishTimestamp, | ||
uint256 _startClaimTimestamp, | ||
uint256 _minEthPayment, | ||
uint256 _maxEthPayment, | ||
uint256 _maxDistributedTokenAmount | ||
) public { | ||
tokenPrice = _tokenPrice; | ||
rewardToken = _rewardToken; | ||
decimals = rewardToken.decimals(); | ||
|
||
require( | ||
_startTimestamp < _finishTimestamp, | ||
"Start timestamp must be less than finish timestamp" | ||
); | ||
require( | ||
_finishTimestamp > now, | ||
"Finish timestamp must be more than current block" | ||
); | ||
startTimestamp = _startTimestamp; | ||
finishTimestamp = _finishTimestamp; | ||
startClaimTimestamp = _startClaimTimestamp; | ||
minEthPayment = _minEthPayment; | ||
maxEthPayment = _maxEthPayment; | ||
maxDistributedTokenAmount = _maxDistributedTokenAmount; | ||
} | ||
|
||
function pay() payable external { | ||
require(msg.value >= minEthPayment, "Less then min amount"); | ||
require(msg.value <= maxEthPayment, "More then max amount"); | ||
require(now >= startTimestamp, "Not started"); | ||
require(now < finishTimestamp, "Ended"); | ||
|
||
uint256 tokenAmount = getTokenAmount(msg.value); | ||
require(tokensForDistribution.add(tokenAmount) <= maxDistributedTokenAmount, "Overfilled"); | ||
|
||
UserInfo storage user = userInfo[msg.sender]; | ||
require(user.totalInvestedETH.add(msg.value) <= maxEthPayment, "More then max amount"); | ||
|
||
tokensForDistribution = tokensForDistribution.add(tokenAmount); | ||
user.totalInvestedETH = user.totalInvestedETH.add(msg.value); | ||
user.total = user.total.add(tokenAmount); | ||
user.debt = user.debt.add(tokenAmount); | ||
|
||
emit TokensDebt(msg.sender, msg.value, tokenAmount); | ||
} | ||
|
||
function getTokenAmount(uint256 ethAmount) | ||
internal | ||
view | ||
returns (uint256) | ||
{ | ||
return ethAmount.mul(10**decimals).div(tokenPrice); | ||
} | ||
|
||
|
||
/// @dev Allows to claim tokens for the specific user. | ||
/// @param _user Token receiver. | ||
function claimFor(address _user) external { | ||
proccessClaim(_user); | ||
} | ||
|
||
/// @dev Allows to claim tokens for themselves. | ||
function claim() external { | ||
proccessClaim(msg.sender); | ||
} | ||
|
||
/// @dev Proccess the claim. | ||
/// @param _receiver Token receiver. | ||
function proccessClaim( | ||
address _receiver | ||
) internal nonReentrant{ | ||
require(now > startClaimTimestamp, "Distribution not started"); | ||
UserInfo storage user = userInfo[_receiver]; | ||
uint256 _amount = user.debt; | ||
if (_amount > 0) { | ||
user.debt = 0; | ||
distributedTokens = distributedTokens.add(_amount); | ||
rewardToken.safeTransfer(_receiver, _amount); | ||
emit TokensWithdrawn(_receiver,_amount); | ||
} | ||
} | ||
|
||
function withdrawETH(uint256 amount) external onlyOwner { | ||
// This forwards all available gas. Be sure to check the return value! | ||
(bool success, ) = msg.sender.call.value(amount)(""); | ||
require(success, "Transfer failed."); | ||
} | ||
|
||
//function safeTransferETH(address to, uint value) internal { | ||
// (bool success,) = to.call{value:value}(new bytes(0)); | ||
// require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); | ||
//} | ||
|
||
function withdrawNotSoldTokens() external onlyOwner { | ||
require(now > finishTimestamp, "Withdraw allowed after stop accept ETH"); | ||
uint256 balance = rewardToken.balanceOf(address(this)); | ||
rewardToken.safeTransfer(msg.sender, balance.add(distributedTokens).sub(tokensForDistribution)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.