Contract Name:
FairPresaleDapp
Contract Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
//pragma experimental ABIEncoderV2;
//import "https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/IUniswapV2Router02.sol";
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
function decimals() external view returns(uint8);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns(uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns(uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns(bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns(uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns(bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns(bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface ERC20 {
function name() external pure returns(string memory);
function symbol() external pure returns(string memory);
function transfer(address to, uint256 value) external returns(bool);
function approve(address spender, uint256 value) external returns(bool);
function transferFrom(address from, address to, uint256 value) external returns(bool);
function totalSupply() external view returns(uint256);
function balanceOf(address who) external view returns(uint256);
function allowance(address owner, address spender) external view returns(uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns(uint256 c) {
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
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 a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns(uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns(uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
address public voter;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
modifier onlyVoter() {
require(msg.sender == voter);
_;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
interface LPToken {
function sync() external;
}
// pragma solidity >=0.5.0;
interface UniswapFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function getPair(address tokenA, address tokenB) external view returns(address pair);
function createPair(address tokenA, address tokenB) external returns(address pair);
}
// pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns(string memory);
function symbol() external pure returns(string memory);
function decimals() external pure returns(uint8);
function totalSupply() external view returns(uint);
function balanceOf(address owner) external view returns(uint);
function allowance(address owner, address spender) external view returns(uint);
function approve(address spender, uint value) external returns(bool);
function transfer(address to, uint value) external returns(bool);
function transferFrom(address from, address to, uint value) external returns(bool);
}
// pragma solidity >=0.6.2;
interface UniswapRouter02 {
function factory() external pure returns(address);
function WETH() external pure returns(address);
function WBNB() external pure returns(address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns(uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns(uint amountToken, uint amountETH, uint liquidity);
function addLiquidityBNB(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns(uint amountToken, uint amountETH, uint liquidity);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns(uint[] memory amounts);
function swapExactBNBForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns(uint[] memory amounts);
// function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns(uint amountOut);
// function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns(uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns(uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns(uint[] memory amounts);
}
interface lpLockDeployerInterface {
function createLPLocker(address _lockingToken, uint256 _lockerEndTimeStamp, string memory _logo, uint256 _lockingAmount) external payable returns (address);
}
contract Consts {
uint constant TOKEN_DECIMALS = 18;
uint8 constant TOKEN_DECIMALS_UINT8 = 18;
uint constant TOKEN_DECIMAL_MULTIPLIER = 10 ** TOKEN_DECIMALS;
bool constant CONTINUE_MINTING = false;
uint256 constant minPlatTokenReq = 1000 * TOKEN_DECIMAL_MULTIPLIER;
uint256 constant airdropTokenPercentage = 2;
}
contract DefiFairCrowdsale is Consts, Ownable
{
event TokenPurchase(
address indexed purchaser,
address indexed beneficiary,
uint256 value,
uint256 amount
);
event Closed();
event RefundsEnabled();
event Refunded(address indexed beneficiary, uint256 weiAmount);
event claimedBack(address indexed beneficiary, uint256 weiAmount);
event Finalized();
string public presaleType = "FAIRLAUNCH";
using SafeMath for uint256;
mapping(address => uint256) public contributors;
mapping(address => uint256) public contributorsTracker;
mapping(address => uint256) public contributorsClaim;
mapping(address => uint256) public contributorsRefundAnytime;
mapping(address => uint256) public contributorsPayoutNumber;
mapping(uint256 => address) public contributorsAddressTracker;
mapping(address => bool) public contributed;
mapping(address => bool) public anytimeRefunded;
mapping(address => bool) public whitelist;
bool public whitelistEnabled;
uint256 public contributorCount;
uint256 public AddWhitelistNumber;
uint256 public RemoveWhitelistNumber;
mapping(uint256 => address) public AddWhitelistTracker;
//mapping(uint256 => address) public RemoveWhitelistTracker;
address[] public AddWhitelistTrackerArray;
//address[] public RemoveWhitelistTrackerArray;
uint256 public presaleGoalReachedTime = 0;
//event Initialized();
//event TimesChanged(uint startTime, uint endTime, uint oldStartTime, uint oldEndTime);
//bool public initialized = false;
//bool public Preaslefinalized = false;
uint256 public buyRate;
uint teamFeePer = 2; // team fees percentage
uint256 public nativeMultiplier = 20;
uint256[2] __min_max_eth;
uint256 public soft_cap;
//uint256 public hard_cap;
uint256 public startTime;
uint256 public endTime;
uint256 public weiRaised;
uint256 public whitelistCoolOff = 600;
uint256 public finalizeTimeout = 600; //604800; //time for presale owner to finalize
address public token;
uint256 public disabledWhitelistTime;
bool public whitelistDisabledInitiated;
bool public isFinalized;
bool public finalizeValid;
bool public vestingEnabled;
bool public refundEnabled;
bool public alternateFee;
uint256 public MaxAllowedContribution;
uint256 public numberOfVest;
uint256 public finalizedTime;
uint256 public vestingPeriod;
uint256 public uniswapPercentage;
uint256 public presaleAmount;
uint256 public uniAmount;
uint256 public totalTokenRequired;
uint256 public extraAmountPerVal;
address public presaleCreator;
address public feeContract;
address public referrerAddr;
// address public uniswapDapAddress;
// address[] teamAddresses;
// uint256[] teamAmounts;
// uint256[] teamFreezeTimes;
//uint256 totalTeamTokensMinted;
constructor(address _token, uint256[2] memory _presaleUniAmount, uint256[2] memory start_end_time, address[2] memory targetWallets, uint256[3] memory _soft_cap_min_max_eth, uint[2] memory _UniPercentage_teamFeePer, uint256[3] memory _extraAmountPer_lockTime_nativeMul, address[2] memory _lpLockDepAndRouter,address[3] memory _altAssets)
//Crowdsale(_rate, targetWallets[0], ERC20(token), _min_max_eth[1])
//TimedCrowdsale(start_end_time[0] > now ? start_end_time[0] : now, start_end_time[1])
//CappedCrowdsale(soft_hard_cap[1] * TOKEN_DECIMAL_MULTIPLIER)
//RefundableCrowdsale(soft_hard_cap[0] * TOKEN_DECIMAL_MULTIPLIER, teamFees, _UniPercentage, targetWallets[1])
{
// require((_govUniPercentage[0] >= 0) && (_govUniPercentage[0] <= 100), "Governance amount is outside of governance limits");
__min_max_eth = [_soft_cap_min_max_eth[1],_soft_cap_min_max_eth[2]];
soft_cap = _soft_cap_min_max_eth[0];
// hard_cap = soft_hard_cap[1] * TOKEN_DECIMAL_MULTIPLIER;
startTime = start_end_time[0];
endTime = start_end_time[1];
token = _token;
MaxAllowedContribution = _soft_cap_min_max_eth[2];
presaleCreator = targetWallets[0];
feeContract = targetWallets[1];
teamFeePer = _UniPercentage_teamFeePer[1];
uniswapPercentage = _UniPercentage_teamFeePer[0];
presaleAmount = _presaleUniAmount[0];
uniAmount = _presaleUniAmount[1];
totalTokenRequired = (presaleAmount + uniAmount) * (teamFeePer + 100) /100;
extraAmountPerVal = _extraAmountPer_lockTime_nativeMul[0] + 100;
locktime = _extraAmountPer_lockTime_nativeMul[1];
nativeMultiplier = _extraAmountPer_lockTime_nativeMul[2];
lpLockDeployer = _lpLockDepAndRouter[0];
ROUTER_ADDRESS = _lpLockDepAndRouter[1];
altAssets = _altAssets;
for(uint256 i=0;i<_altAssets.length;i++){
validPairPartner[altAssets[i]] = true;
}
}
/*
function checkContributorValidity(address contributor_addr) public view returns(uint256) {
return contributors[contributor_addr];
}
*/
function checkRate() public view returns(uint256) {
return buyRate;
}
function minEthContribution() public view returns(uint256) {
return __min_max_eth[0];
}
function maxEthContribution() public view returns(uint256) {
return __min_max_eth[1];
}
function presaleStartTime() public view returns(uint256) {
return startTime;
}
function presaleEndTime() public view returns(uint256) {
return endTime;
}
/*
function mintForPlatform(address _platAddrs) public onlyOwner {
require(_platAddrs != address(0), "platform addr cant be zero");
uint256 platFee = (presaleAmount*teamFeePer)/100;
ERC20(token).transfer(_platAddrs, platFee);
}
function mintForUniswap(address uniswapDep) public onlyOwner {
require(uniswapDep != address(0x0),"uniswapDep addr cannot be zero");
require(ERC20(token).transfer(uniswapDep, (uniAmount*extraAmountPerVal)/100),"unable to mint for uniDep from presale");
}
*/
// function resetUserEthAmount(address contributor_addr) onlyOwner public {
// contributors[contributor_addr] = 0;
//}
/**
* @dev override hasClosed to add minimal value logic
* @return true if remained to achieve less than minimal
*/
function hasClosed() public view returns(bool) {
//bool remainValue = (hard_cap - weiRaised) < __min_max_eth[0];
return (block.timestamp > endTime);// || remainValue;
}
function CheckSoftCap() public view returns(uint256) {
return soft_cap;
}
/*
function CheckHardCap() public view returns(uint256) {
return hard_cap;
}
*/
function CheckTotalEthRaised() public view returns(uint256) {
return weiRaised;
}
/*
* @dev override purchase validation to add extra value logic.
* @return true if sended more than minimal value
*/
function _preValidatePurchase(
address _beneficiary,
uint256 _weiAmount
)
internal {
require(msg.value >= __min_max_eth[0]);
// require(msg.value >= 0);
require(msg.value <= (__min_max_eth[1])); // it should be 10% in mainnet launch ***********************
// require(msg.value <= 1000000000000000000);
// require((weiRaised + _weiAmount) <= hard_cap,"contribution reaching over hcap");
require(_beneficiary != address(0));
require(_weiAmount != 0);
}
function addToWhitelist(address WhitelistAddress) public onlyOwner {
// require(!whitelist[WhitelistAddress], "already whitelisted");
whitelist[WhitelistAddress] = true;
AddWhitelistTracker[AddWhitelistNumber] = WhitelistAddress;
AddWhitelistNumber++;
}
function removeFromWhitelist(address WhitelistAddress) public onlyOwner {
require(whitelist[WhitelistAddress], "not in whitelist!");
whitelist[WhitelistAddress] = false;
//RemoveWhitelistTracker[RemoveWhitelistNumber] = WhitelistAddress;
RemoveWhitelistNumber++;
}
function enableWhitelist() public onlyOwner {
require(!whitelistEnabled, "whitelist already enabled");
whitelistEnabled = true;
}
function disableWhitelist() public onlyOwner {
require(whitelistEnabled, "whitelist already disabled");
whitelistEnabled = false;
disabledWhitelistTime = block.timestamp + whitelistCoolOff;
whitelistDisabledInitiated = true;
}
function getAddlist() public view returns(address[] memory){
address[] memory AddList = new address[](AddWhitelistNumber);
for (uint256 i = 0; i < AddWhitelistNumber; i++) {
if(whitelist[AddWhitelistTracker[i]]){
AddList[i] = AddWhitelistTracker[i];
}
else {
AddList[i] = address(0x0);
}
}
return AddList;
}
/*
function getRemovelist() public view returns(address[] memory) {
address[] memory RemoveList = new address[](RemoveWhitelistNumber);
for (uint256 i = 0; i < RemoveWhitelistNumber; i++) {
RemoveList[i] = RemoveWhitelistTracker[i];
}
return RemoveList;
}
*/
/*
function getPresaleDataAddr() view returns(address[] memory, uint256[7] memory) {
address[] memory PresaleDataAddr = new address[](AddWhitelistNumber);
for (uint256 i = 0; i < AddWhitelistNumber; i++) {
PresaleDataAddr[i] = AddWhitelistTracker[i]; //******************************************** NEED UPDATE TO ADD CORRECT ADDRESS DATA***************************************************
}
return (PresaleDataAddr,getPresaleDataUint());
}
*/
function getPresaleData() public view returns(uint256[10] memory,bool[4] memory, string memory) {
uint256[10] memory PresaleDataUint;
bool[4] memory presaleDataBool;
PresaleDataUint = [soft_cap,presaleAmount,__min_max_eth[0],__min_max_eth[1],startTime,endTime,weiRaised,buyRate,uniAmount,uniswapPercentage];
presaleDataBool = [isFinalized,finalizeValid,vestingEnabled,refundEnabled];
return (PresaleDataUint,presaleDataBool,presaleType);
}
function getContributorData() public view returns(address[] memory,uint256[] memory) {
// address[] memory WalletList = new address[](KYCsverifiedNumber);
address[] memory contributorAddresses = new address[](contributorCount);
uint256[] memory contributedValues = new uint256[](contributorCount);
for (uint256 i = 0; i < contributorCount;i++){
contributorAddresses[i] = contributorsAddressTracker[i];
contributedValues[i] = contributors[contributorsAddressTracker[i]];
}
return (contributorAddresses,contributedValues);
}
/**
* @dev fallback function ***DO NOT OVERRIDE***
*/
receive() external payable {
require(block.timestamp > disabledWhitelistTime, "In whitelist disabled cool Off");
require(!anytimeRefunded[msg.sender], "User used anytime refund!"); //checking if user refunded from this presale at anytime
if (whitelistEnabled) {
require(whitelist[msg.sender], "user not whitelisted");
}
require(contributors[msg.sender] <= (MaxAllowedContribution - msg.value),"contribution over max allowed");
buyTokens(msg.sender);
contributors[msg.sender] += msg.value;
contributorsTracker[msg.sender] += msg.value;
if(!contributed[msg.sender]){
contributorsAddressTracker[contributorCount] = msg.sender;
contributed[msg.sender] = true;
contributorCount++;
}
}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) internal {
require(msg.sender == tx.origin,"can't contribute via contracts");
require(block.timestamp > disabledWhitelistTime, "In whitelist disabled cool Off");
require (block.timestamp >= startTime && block.timestamp < endTime,"presale not active");
require(!anytimeRefunded[msg.sender], "User used anytime refund!"); //checking if user refunded from this presale at anytime
if (whitelistEnabled) {
require(whitelist[msg.sender], "user not whitelisted");
}
uint256 weiAmount = msg.value;
_preValidatePurchase(_beneficiary, weiAmount);
// calculate token amount to be created
uint256 tokens = _getTokenAmount(weiAmount);
// update state
weiRaised += weiAmount;
//_processPurchase(_beneficiary, tokens);
emit TokenPurchase(
msg.sender,
_beneficiary,
weiAmount,
tokens
);
// _updatePurchasingState(_beneficiary, weiAmount);
//_forwardFunds();
//_postValidatePurchase(_beneficiary, weiAmount);
}
function _getTokenAmount(uint256 _weiAmount)
internal view returns(uint256) {
return _weiAmount*buyRate/(1 ether);
// return _weiAmount.mul(rate);
}
function claimTokens() public {
require(!refundEnabled,"presale was refunded");
require(!vestingEnabled,"please use vesting method to claim");
require(isFinalized, "Not Finalized yet!");
require(finalizeValid, "presale Failed!"); //checking if presale succeeded or not
require(!(contributors[msg.sender] == 0), "user has no more tokens to claim!");
uint256 tokenValue = (uint256(contributors[msg.sender]).mul(uint256(buyRate))).div(1 ether);
// uint256 tokenValueDecimalOptimized = (tokenValue.mul(10 ** uint256(seeDecimals(token)))).div(1 ether);
contributors[msg.sender] = 0;
ERC20(token).transfer(msg.sender, tokenValue);
contributorsClaim[msg.sender] = tokenValue;
}
function vestToken() public {
// require(!tokenDropFlag,"can't vest when token drop enabled!");
require(!refundEnabled,"presale was refunded");
require(vestingEnabled,"vesting not enabled");
require(isFinalized, "Not Finalized yet!");
require(finalizeValid, "presale Failed!"); //checking if presale succeeded or not
require(!(contributors[msg.sender] == 0), "user has no more tokens to claim!");
require(contributorsPayoutNumber[msg.sender] < numberOfVest,"all tokens vested");
uint256 CurrentPayoutRounds = (((block.timestamp).sub(finalizedTime)).div(vestingPeriod)).add(1); // need to add 1 to allow partial token vest right away after presale
if (CurrentPayoutRounds >= numberOfVest){
CurrentPayoutRounds = numberOfVest;
}
uint256 userPayoutRounds = CurrentPayoutRounds.sub(contributorsPayoutNumber[msg.sender]);
require(userPayoutRounds > 0 && userPayoutRounds <= numberOfVest,"not in user claim window");
contributorsPayoutNumber[msg.sender] = CurrentPayoutRounds;
uint256 tokenValue = (((uint256(contributorsTracker[msg.sender]).mul(uint256(buyRate))).div(1 ether)).mul(userPayoutRounds)).div(numberOfVest);
// uint256 tokenValueDecimalOptimized = (tokenValue.mul(10 ** uint256(seeDecimals(token)))).div(1 ether);
uint256 totalTokensLeftForUser = (uint256(contributors[msg.sender]).mul(uint256(buyRate))).div(1 ether);
require(tokenValue <= totalTokensLeftForUser,"can't claim more than allowed");
uint256 contributionsClaiming = contributorsTracker[msg.sender].mul(userPayoutRounds).div(numberOfVest);
if(contributionsClaiming >= contributors[msg.sender]){
contributors[msg.sender] = 0;
}
else{
contributors[msg.sender] = contributors[msg.sender].sub(contributionsClaiming);
}
ERC20(token).transfer(msg.sender, tokenValue);
contributorsClaim[msg.sender] = contributorsClaim[msg.sender].add(tokenValue);
}
function enableVesting(uint256 _numOfVest, uint256 _vestingPeriod) public{
require(_numOfVest > 1,"num of vest has to be grtr than 1");
require(_vestingPeriod > 0,"vesting period invalid");
require(block.timestamp < startTime.sub(600),"can't enable vest after presale start");
require(!vestingEnabled,"vesting already enabled");
//require(!tokenDropFlag, "can't enable vest when airdrop is on");
require(msg.sender == presaleCreator); // checking for presale owner address
vestingEnabled = true;
numberOfVest = _numOfVest;
vestingPeriod = _vestingPeriod;
}
function disableVesting() public {
require(msg.sender == presaleCreator);
require(vestingEnabled,"vesting already disabled");
require(!isFinalized,"presale already finalized");
vestingEnabled = false;
}
function claimRefund() public {
require(isFinalized, "not finalized");
require(!(goalReached()) || !finalizeValid, "goal reached or presale succeeded");
refund(msg.sender);
}
function claimRefundAnytime() public {
require(!anytimeRefunded[msg.sender], "already refunded!");
uint256 userContributed = contributors[msg.sender];
require(userContributed > 0, "nothing to claim");
require(!isFinalized, "already finalized!");
require(!finalizeValid, "already succesfully finalized");
require(block.timestamp < endTime.sub(finalizeTimeout), "withdrawal window expired!");
// require(!goalReached() || !finalizeValid,"goal reached");
contributorsRefundAnytime[msg.sender] = userContributed; // added for V3 -- need to check
weiRaised = weiRaised.sub(userContributed); // Subtract from total eth raised
anytimeRefunded[msg.sender] = true;
refundAnytime(msg.sender,userContributed);
}
function refund(address investor) internal { //have to see if onlyOwner works
require(refundEnabled,"refund not enabled");
uint256 depositedValue = contributors[investor];
require(depositedValue > 0, "User has no investment to claim");
contributors[investor] = 0;
(bool refundSucess,) = payable(investor).call{value:depositedValue}("");
require(refundSucess,"refund failed");
emit Refunded(investor, depositedValue);
}
function refundAnytime(address investor, uint256 _contributed) internal { // have to see if onlyOwner works
//require(state == State.Refunding);
//uint256 depositedValue = contributors[investor];
//require(depositedValue > 0, "User has no investment to claim");
uint256 penalty = _contributed.mul(20).div(100);
uint256 refundValue = _contributed.sub(penalty);
contributors[investor] = 0; // added for V3 -- need to check
contributorsTracker[investor] = 0; // added for V3 -- need to check
(bool feeContractPay,) = payable(feeContract).call{value:penalty}("");
(bool investorPay,) = payable(investor).call{value:refundValue}("");
require(feeContractPay && investorPay,"anytime refund failed at payment");
emit claimedBack(investor, _contributed);
}
function finalize(address[2] memory __finalizeInfo, uint256 refPer, bool validFinalize) onlyOwner public returns(uint256) {
require(!isFinalized,"already finalized");
require(hasClosed(),"not closed");
referrerAddr = __finalizeInfo[0];
presaleCreator = __finalizeInfo[1];
// uniswapDapAddress = __finalizeInfo[2];
finalizeValid = validFinalize;
if (goalReached() && finalizeValid) {
setRate();
close(presaleCreator, referrerAddr, refPer);
} else {
enableRefunds();
}
finalizedTime = block.timestamp;
emit Finalized();
isFinalized = true;
/*
if(tokenDropFlag && finalizeValid){
tokenDrop();
}
*/
return 1;
}
/*
function mintForUniswap(address _uniswapDapp) onlyOwner public {
IERC20(token).transfer(_uniswapDapp,uniAmount);
}
*/
function mintForPlatform(address _platform, address _referrer, uint256 _refPer, bool tokenFeeToRef) public onlyOwner returns(bool) {
if(!alternateFee){
require(_platform != address(0), "platform addr cant be zero");
uint256 platFee = (presaleAmount*teamFeePer)/100;
uint256 refFee;
if(tokenFeeToRef){
refFee = platFee*_refPer/100;
ERC20(token).transfer(_platform, platFee - (refFee));
ERC20(token).transfer(_referrer, refFee);
}
else{
ERC20(token).transfer(_platform, platFee);
}
}
return true;
}
/*
function mintForPlatform(address _platform) onlyOwner public {
uint256 platformFee = (presaleAmount*teamFeePer)/100;
IERC20(token).transfer(_platform,platformFee);
}
*/
function finalizeAnytime(address[3] memory __finalizeInfo, bool validFinalize) onlyOwner public returns(uint256) {
require(!isFinalized, "presale already finalized");
// require(hasClosed());
referrerAddr = __finalizeInfo[0];
presaleCreator = __finalizeInfo[1];
// uniswapDapAddress = __finalizeInfo[2];
finalizeValid = validFinalize;
enableRefunds();
emit Finalized();
isFinalized = true;
return 1;
}
function enableRefunds() internal {
refundEnabled = true;
emit RefundsEnabled();
}
function setRate() internal{
buyRate = (presaleAmount*(1 ether))/CheckTotalEthRaised();
}
function getBackTokens() public {
// require(block.timestamp > closingTime.add(burnDeltaTime), "cannot withdraw yet");
require(msg.sender == presaleCreator, "initiator is not presale owner!");
// require(hasClosed(), "presale not closed!");
require(isFinalized, "presale not finalized!");
require(!finalizeValid, "finalize was valid");
require(IERC20(token).transfer(presaleCreator, IERC20(token).balanceOf(address(this))),"cannot transfer token back");
}
function selectNativeOnlyFee() public {
require(msg.sender == presaleCreator, "initiator is not presale owner!");
require(!isFinalized, "presale already finalized!");
alternateFee = true;
teamFeePer = (teamFeePer * nativeMultiplier)/10;
}
function close(address __Creator, address _referrerAddr, uint256 _refPer) internal {
require(!isFinalized,"presale already finalized");
emit Closed();
uint256 feesAmount = address(this).balance.mul(teamFeePer).div(100);
if(_refPer > 0){
uint256 refAmount = feesAmount.mul(_refPer).div(100);
(bool refPay,) = payable(_referrerAddr).call{value:refAmount}("");
(bool feeContractClosePay,) = payable(feeContract).call{value:feesAmount.sub(refAmount)}("");
require(refPay && feeContractClosePay,"unable to process ref or fee pay");
}
else{
(bool feeContractOnlyPay,) = payable(feeContract).call{value:feesAmount}("");
require(feeContractOnlyPay,"unable to process fee pay");
}
uint256 uniswapAmount = address(this).balance.mul(uniswapPercentage).div(100);
// uint256 GoverningAmount = address(this).balance.mul(gov).div(100);
require(address(this).balance >= uniswapAmount, "Not Enough Fund to Transfer");
// require(address(this).balance > GoverningAmount, "Not Enough Fund to Transfer");
// payable(__uniswapDep).transfer(uniswapAmount);
AddLiquidity(uniAmount,uniswapAmount);
// __GovContract.transfer(GoverningAmount);
if(address(this).balance != 0){
(bool creatorPay,) = payable(__Creator).call{value:address(this).balance}("");
require(creatorPay,"unable to pay creator");
}
}
function goalReached() public view returns(bool) {
return weiRaised >= soft_cap;
}
function presaleEnded() public view returns(bool) {
return block.timestamp > endTime;
}
mapping(address => bool) public validPairPartner;
uint256 public hundred = 100;
uint256 public locktime;
address public ROUTER_ADDRESS;
//address public dead = 0x000000000000000000000000000000000000dEaD;
address[3] public altAssets;
address public storedLPAddress;
address public lockerAddress;
bool public addLiquidityComplete;
address public alternativeCurrency;
bool public useAlternativeCurrency;
uint256 public returnVal;
address public lpLockDeployer;
string public logo = " ";
function Approve(address _token) internal returns (bool) {
uint256 amountIn = 100000000000000000000000000000000000000000000000000000000000000000000000000000;
ERC20(_token).approve(ROUTER_ADDRESS, amountIn);
return true;
}
function ApproveLock(address _lp, address _lockDeployer) internal returns (bool) {
uint256 amountIn = 100000000000000000000000000000000000000000000000000000000000000000000000000000;
ERC20(_lp).approve(_lockDeployer, amountIn);
return true;
}
function getWrapAddr() public view returns (address){
return UniswapRouter02(ROUTER_ADDRESS).WETH();
}
function getpair(address _token1, address _token2) internal returns (address) {
if (UniswapFactory(UniswapRouter02(ROUTER_ADDRESS).factory()).getPair(_token1, _token2) != address(0)) {
return UniswapFactory(UniswapRouter02(ROUTER_ADDRESS).factory()).getPair(_token1, _token2);
} else {
return UniswapFactory(UniswapRouter02(ROUTER_ADDRESS).factory()).createPair(_token1, _token2);
}
}
function setAlternateCurrency(address _newCurrency) public {
require(_newCurrency != address(0),"currency cannot be Zero addr");
// require(swapRouterMap[_swapRouter],"invalid router");
require(validPairPartner[_newCurrency],"invalid asset selected");
require(!addLiquidityComplete,"Liquidity is added already");
require(msg.sender == presaleCreator,"not the presale creator");
// swapRouter_Address = _swapRouter;
alternativeCurrency = _newCurrency;
useAlternativeCurrency = true;
}
function revertToNative() public{
require(!addLiquidityComplete,"Liquidity is added already");
require(msg.sender == presaleCreator,"not the presale creator");
useAlternativeCurrency = false;
}
function getAmountsMinToken(address _tokenAddress, uint256 _ethIN) public view returns(uint256) {
// UniswapRouter02 pancakeRouter = UniswapRouter02(_router);
// generate the pair path of token -> weth
uint256[] memory amountMinArr;
uint256 AmountMin;
address[] memory path = new address[](2);
path[0] = getWrapAddr();
path[1] = address(_tokenAddress);
amountMinArr = UniswapRouter02(ROUTER_ADDRESS).getAmountsOut(_ethIN, path);
AmountMin = uint256(amountMinArr[1]);
return AmountMin;
}
function swapETHForTokens(uint256 _nativeForDex) private {
require(useAlternativeCurrency,"alt currency not selected");
address[] memory path = new address[](2);
//path[0] = address(this);
path[0] = getWrapAddr();
path[1] = alternativeCurrency;
Approve(alternativeCurrency);
// make the swap
UniswapRouter02(ROUTER_ADDRESS).swapExactETHForTokens{value:_nativeForDex}(
getAmountsMinToken(alternativeCurrency,_nativeForDex),
path,
address(this),
block.timestamp + (300)
);
returnVal = ERC20(alternativeCurrency).balanceOf(address(this));
}
function AddLiquidity(uint256 amountTokenDesired, uint256 nativeForDex) internal {
// require(validPairPartner[_pairAlternative], "This is not a valid pair partner");
uint256 amountETH = nativeForDex;
uint256 amountETHMin = amountETH - (amountETH * (10) / (100));
//uint256 amountTokenToAddLiq = amountTokenDesired * (hundred) / (extraAmountPerVal);
uint256 amountTokenToAddLiq = amountTokenDesired;
uint256 amountTokenMin = amountTokenToAddLiq - (amountTokenToAddLiq * (10) / (100));
uint256 LP_WBNB_exp_balance;
uint256 LP_token_balance;
uint256 tokenToSend;
if (useAlternativeCurrency) {
swapETHForTokens(nativeForDex);
storedLPAddress = getpair(token, alternativeCurrency);
LP_WBNB_exp_balance = ERC20(alternativeCurrency).balanceOf(storedLPAddress);
LP_token_balance = ERC20(token).balanceOf(storedLPAddress);
}
else{
storedLPAddress = getpair(token, getWrapAddr());
LP_WBNB_exp_balance = ERC20(getWrapAddr()).balanceOf(storedLPAddress);
LP_token_balance = ERC20(token).balanceOf(storedLPAddress);
}
if (storedLPAddress != address(0x0) && (LP_WBNB_exp_balance > 0 && LP_token_balance <= 0)) {
tokenToSend = amountTokenToAddLiq * (LP_WBNB_exp_balance) / (amountETH);
ERC20(token).transfer(storedLPAddress, tokenToSend);
LPToken(storedLPAddress).sync();
// sync after adding token
}
Approve(token);
if (useAlternativeCurrency) {
UniswapRouter02(ROUTER_ADDRESS).addLiquidity(token, alternativeCurrency,amountTokenDesired,ERC20(alternativeCurrency).balanceOf(address(this)),amountTokenDesired,ERC20(alternativeCurrency).balanceOf(address(this)),address(this), block.timestamp + (300));
}
else{
UniswapRouter02(ROUTER_ADDRESS).addLiquidityETH{value:amountETH}(token, amountTokenToAddLiq, amountTokenMin, amountETHMin, address(this), block.timestamp + (300));
}
addLiquidityComplete = true;
ApproveLock(storedLPAddress,lpLockDeployer);
lockerAddress = lpLockDeployerInterface(lpLockDeployer).createLPLocker(storedLPAddress,locktime,logo,ERC20(storedLPAddress).balanceOf(address(this)));
}
/*
function getAltAssetData() public view returns(address[] memory, string[] memory){
address[] memory altAssetData = new address[](altAssets.length);
// string[] memory altListName = new string[](altAssets.length);
string[] memory altListSym = new string[](altAssets.length);
for(uint256 i=0;i<altAssets.length;i++){
altAssetData[i] = altAssets[i];
// altListName[i] = ERC20(altAssets[i]).name();
altListSym[i] = ERC20(altAssets[i]).symbol();
}
return(altAssetData,altListSym);
}
*/
}
contract FairPresaleDapp is Consts, Ownable {
using SafeMath for uint256;
address public feeContract;
address public lpLockDeployer;
uint256 public teamFee = 2;
// uint256 public extraAmountPer = 2;
uint256 public nativeMultiplier = 20;
address[3] public altAssets;
constructor(address _feeContract, address _lpLockDeployer, address[3] memory _altAssets) {
feeContract = _feeContract;
lpLockDeployer = _lpLockDeployer;
altAssets = _altAssets;
}
function CreatePresaleFair(address[4] memory presaleAddressInput_Router, uint256[2] memory start_end_time, uint256[5] memory softcap_preAmnt_uniAmnt_min_max_eth, uint256 uniPercentage, uint256[2] memory extraAmountPer_lockTime) public returns(address) {
DefiFairCrowdsale PresaleContract = new DefiFairCrowdsale(presaleAddressInput_Router[2], [softcap_preAmnt_uniAmnt_min_max_eth[1],softcap_preAmnt_uniAmnt_min_max_eth[2]], start_end_time, [presaleAddressInput_Router[1],feeContract], [softcap_preAmnt_uniAmnt_min_max_eth[0],softcap_preAmnt_uniAmnt_min_max_eth[3], softcap_preAmnt_uniAmnt_min_max_eth[4]], [uniPercentage,teamFee],[extraAmountPer_lockTime[0],extraAmountPer_lockTime[1],nativeMultiplier],[lpLockDeployer,presaleAddressInput_Router[3]],altAssets);
PresaleContract.transferOwnership(presaleAddressInput_Router[0]);
return address(PresaleContract);
}
function CheckBlockTimestamp() public view returns(uint256) {
return block.timestamp;
}
function updateNativeMultiplier(uint256 _newMultiplier) public onlyOwner {
nativeMultiplier = _newMultiplier;
}
function updateTeamFee(uint256 _newTeamFee) public onlyOwner {
teamFee = _newTeamFee;
}
function updateFeeContract(address _newFeeContract) public onlyOwner {
feeContract = _newFeeContract;
}
function updateAltAssets(uint index, address _newAltAsset) public onlyOwner {
altAssets[index] = _newAltAsset;
}
}