/**
*Submitted for verification at Etherscan.io on 2021-01-09
*/
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.0;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
function ceil(uint a, uint m) internal pure returns (uint r) {
return (a + m - 1) / m * m;
}
}
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
address payable public owner;
event OwnershipTransferred(address indexed _from, address indexed _to);
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address payable _newOwner) public onlyOwner {
owner = _newOwner;
emit OwnershipTransferred(msg.sender, _newOwner);
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// ----------------------------------------------------------------------------
interface IToken {
function transfer(address to, uint256 tokens) external returns (bool success);
function burnTokens(uint256 _amount) external;
function balanceOf(address tokenOwner) external view returns (uint256 balance);
}
contract Presale is Owned {
using SafeMath for uint256;
bool public isPresaleOpen;
//@dev ERC20 token address and decimals
address public tokenAddress;
uint256 public tokenDecimals = 9;
//@dev amount of tokens per ether 100 indicates 1 token per eth
uint256 public tokenRatePerEth = 137_00;
//@dev decimal for tokenRatePerEth,
//2 means if you want 100 tokens per eth then set the rate as 100 + number of rateDecimals i.e => 10000
uint256 public rateDecimals = 2;
//@dev max and min token buy limit per account
uint256 public minEthLimit = 500 finney;
uint256 public maxEthLimit = 3 ether;
mapping(address => uint256) public usersInvestments;
constructor() public {
owner = msg.sender;
}
function startPresale() external onlyOwner{
require(!isPresaleOpen, "Presale is open");
isPresaleOpen = true;
}
function closePrsale() external onlyOwner{
require(isPresaleOpen, "Presale is not open yet.");
isPresaleOpen = false;
}
function setTokenAddress(address token) external onlyOwner {
require(tokenAddress == address(0), "Token address is already set.");
require(token != address(0), "Token address zero not allowed.");
tokenAddress = token;
}
function setTokenDecimals(uint256 decimals) external onlyOwner {
tokenDecimals = decimals;
}
function setMinEthLimit(uint256 amount) external onlyOwner {
minEthLimit = amount;
}
function setMaxEthLimit(uint256 amount) external onlyOwner {
maxEthLimit = amount;
}
function setTokenRatePerEth(uint256 rate) external onlyOwner {
tokenRatePerEth = rate;
}
function setRateDecimals(uint256 decimals) external onlyOwner {
rateDecimals = decimals;
}
receive() external payable{
require(isPresaleOpen, "Presale is not open.");
require(
usersInvestments[msg.sender].add(msg.value) <= maxEthLimit
&& usersInvestments[msg.sender].add(msg.value) >= minEthLimit,
"Installment Invalid."
);
//@dev calculate the amount of tokens to transfer for the given eth
uint256 tokenAmount = getTokensPerEth(msg.value);
require(IToken(tokenAddress).transfer(msg.sender, tokenAmount), "Insufficient balance of presale contract!");
usersInvestments[msg.sender] = usersInvestments[msg.sender].add(msg.value);
//@dev send received funds to the owner
owner.transfer(msg.value);
}
function getTokensPerEth(uint256 amount) internal view returns(uint256) {
return amount.mul(tokenRatePerEth).div(
10**(uint256(18).sub(tokenDecimals).add(rateDecimals))
);
}
function burnUnsoldTokens() external onlyOwner {
require(!isPresaleOpen, "You cannot burn tokens untitl the presale is closed.");
IToken(tokenAddress).burnTokens(IToken(tokenAddress).balanceOf(address(this)));
}
function getUnsoldTokens() external onlyOwner {
require(!isPresaleOpen, "You cannot get tokens until the presale is closed.");
IToken(tokenAddress).transfer(owner, IToken(tokenAddress).balanceOf(address(this)) );
}
}
{
"compilationTarget": {
"browser/presale1.sol": "Presale"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"burnUnsoldTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closePrsale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getUnsoldTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPresaleOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxEthLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minEthLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMaxEthLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMinEthLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"decimals","type":"uint256"}],"name":"setRateDecimals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setTokenAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"decimals","type":"uint256"}],"name":"setTokenDecimals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"setTokenRatePerEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenRatePerEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersInvestments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]