Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/PreSale/PreSaleSource.sol": {
"content": "//SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.20;\r
\r
abstract contract ReentrancyGuard {\r
uint256 private constant _NOT_ENTERED = 1;\r
uint256 private constant _ENTERED = 2;\r
\r
uint256 private _status;\r
\r
constructor() {\r
_status = _NOT_ENTERED;\r
}\r
\r
modifier nonReentrant() {\r
_nonReentrantBefore();\r
_;\r
_nonReentrantAfter();\r
}\r
\r
function _nonReentrantBefore() private {\r
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");\r
\r
_status = _ENTERED;\r
}\r
\r
function _nonReentrantAfter() private {\r
_status = _NOT_ENTERED;\r
}\r
}\r
\r
abstract contract Context {\r
function _msgSender() internal view virtual returns (address) {\r
return msg.sender;\r
}\r
\r
function _msgData() internal view virtual returns (bytes calldata) {\r
return msg.data;\r
}\r
}\r
\r
abstract contract Ownable is Context {\r
address private _owner;\r
\r
event OwnershipTransferred(\r
address indexed previousOwner,\r
address indexed newOwner\r
);\r
\r
constructor() {\r
_transferOwnership(_msgSender());\r
}\r
\r
modifier onlyOwner() {\r
_checkOwner();\r
_;\r
}\r
\r
function owner() public view virtual returns (address) {\r
return _owner;\r
}\r
\r
function _checkOwner() internal view virtual {\r
require(owner() == _msgSender(), "Ownable: caller is not the owner");\r
}\r
\r
function renounceOwnership() public virtual onlyOwner {\r
_transferOwnership(address(0));\r
}\r
\r
function transferOwnership(address newOwner) public virtual onlyOwner {\r
require(\r
newOwner != address(0),\r
"Ownable: new owner is the zero address"\r
);\r
_transferOwnership(newOwner);\r
}\r
\r
function _transferOwnership(address newOwner) internal virtual {\r
address oldOwner = _owner;\r
_owner = newOwner;\r
emit OwnershipTransferred(oldOwner, newOwner);\r
}\r
}\r
\r
library Address {\r
function isContract(address account) internal view returns (bool) {\r
return account.code.length > 0;\r
}\r
\r
function sendValue(address payable recipient, uint256 amount) internal {\r
require(\r
address(this).balance >= amount,\r
"Address: insufficient balance"\r
);\r
\r
(bool success, ) = recipient.call{value: amount}("");\r
require(\r
success,\r
"Address: unable to send value, recipient may have reverted"\r
);\r
}\r
\r
function functionCall(\r
address target,\r
bytes memory data\r
) internal returns (bytes memory) {\r
return\r
functionCallWithValue(\r
target,\r
data,\r
0,\r
"Address: low-level call failed"\r
);\r
}\r
\r
function functionCall(\r
address target,\r
bytes memory data,\r
string memory errorMessage\r
) internal returns (bytes memory) {\r
return functionCallWithValue(target, data, 0, errorMessage);\r
}\r
\r
function functionCallWithValue(\r
address target,\r
bytes memory data,\r
uint256 value\r
) internal returns (bytes memory) {\r
return\r
functionCallWithValue(\r
target,\r
data,\r
value,\r
"Address: low-level call with value failed"\r
);\r
}\r
\r
function functionCallWithValue(\r
address target,\r
bytes memory data,\r
uint256 value,\r
string memory errorMessage\r
) internal returns (bytes memory) {\r
require(\r
address(this).balance >= value,\r
"Address: insufficient balance for call"\r
);\r
(bool success, bytes memory returndata) = target.call{value: value}(\r
data\r
);\r
return\r
verifyCallResultFromTarget(\r
target,\r
success,\r
returndata,\r
errorMessage\r
);\r
}\r
\r
function functionStaticCall(\r
address target,\r
bytes memory data\r
) internal view returns (bytes memory) {\r
return\r
functionStaticCall(\r
target,\r
data,\r
"Address: low-level static call failed"\r
);\r
}\r
\r
function functionStaticCall(\r
address target,\r
bytes memory data,\r
string memory errorMessage\r
) internal view returns (bytes memory) {\r
(bool success, bytes memory returndata) = target.staticcall(data);\r
return\r
verifyCallResultFromTarget(\r
target,\r
success,\r
returndata,\r
errorMessage\r
);\r
}\r
\r
function functionDelegateCall(\r
address target,\r
bytes memory data\r
) internal returns (bytes memory) {\r
return\r
functionDelegateCall(\r
target,\r
data,\r
"Address: low-level delegate call failed"\r
);\r
}\r
\r
function functionDelegateCall(\r
address target,\r
bytes memory data,\r
string memory errorMessage\r
) internal returns (bytes memory) {\r
(bool success, bytes memory returndata) = target.delegatecall(data);\r
return\r
verifyCallResultFromTarget(\r
target,\r
success,\r
returndata,\r
errorMessage\r
);\r
}\r
\r
function verifyCallResultFromTarget(\r
address target,\r
bool success,\r
bytes memory returndata,\r
string memory errorMessage\r
) internal view returns (bytes memory) {\r
if (success) {\r
if (returndata.length == 0) {\r
require(isContract(target), "Address: call to non-contract");\r
}\r
return returndata;\r
} else {\r
_revert(returndata, errorMessage);\r
}\r
}\r
\r
function verifyCallResult(\r
bool success,\r
bytes memory returndata,\r
string memory errorMessage\r
) internal pure returns (bytes memory) {\r
if (success) {\r
return returndata;\r
} else {\r
_revert(returndata, errorMessage);\r
}\r
}\r
\r
function _revert(\r
bytes memory returndata,\r
string memory errorMessage\r
) private pure {\r
if (returndata.length > 0) {\r
assembly {\r
let returndata_size := mload(returndata)\r
revert(add(32, returndata), returndata_size)\r
}\r
} else {\r
revert(errorMessage);\r
}\r
}\r
}\r
\r
interface IERC20 {\r
event Transfer(address indexed from, address indexed to, uint256 value);\r
\r
event Approval(\r
address indexed owner,\r
address indexed spender,\r
uint256 value\r
);\r
\r
function totalSupply() external view returns (uint256);\r
\r
function balanceOf(address account) external view returns (uint256);\r
\r
function transfer(address to, uint256 amount) external returns (bool);\r
\r
function allowance(\r
address owner,\r
address spender\r
) external view returns (uint256);\r
\r
function approve(address spender, uint256 amount) external returns (bool);\r
\r
function transferFrom(\r
address from,\r
address to,\r
uint256 amount\r
) external returns (bool);\r
}\r
\r
interface IERC20Metadata is IERC20 {\r
function name() external view returns (string memory);\r
\r
function symbol() external view returns (string memory);\r
\r
function decimals() external view returns (uint8);\r
}\r
\r
interface Aggregator {\r
function latestRoundData()\r
external\r
view\r
returns (\r
uint80 roundId,\r
int256 answer,\r
uint256 startedAt,\r
uint256 updatedAt,\r
uint80 answeredInRound\r
);\r
}\r
\r
contract LILPENGU_Presale_Source is ReentrancyGuard, Ownable {\r
uint256 public overalllRaised;\r
uint256 public presaleId;\r
uint256 public USDT_MULTIPLIER;\r
uint256 public ETH_MULTIPLIER;\r
address public fundReceiver;\r
uint256 public uniqueBuyers;\r
address[] private participantsList;\r
\r
struct PresaleData {\r
uint256 startTime;\r
uint256 endTime;\r
uint256 price;\r
uint256 nextStagePrice;\r
uint256 Sold;\r
uint256 tokensToSell;\r
uint256 UsdtHardcap;\r
uint256 amountRaised;\r
bool Active;\r
bool isEnableClaim;\r
}\r
\r
struct VestingData {\r
uint256 vestingStartTime;\r
uint256 initialClaimPercent;\r
uint256 vestingTime;\r
uint256 vestingPercentage;\r
uint256 totalClaimCycles;\r
}\r
\r
struct UserData {\r
uint256 investedAmount;\r
uint256 claimAt;\r
uint256 claimAbleAmount;\r
uint256 claimedVestingAmount;\r
uint256 claimedAmount;\r
uint256 claimCount;\r
uint256 activePercentAmount;\r
}\r
\r
IERC20Metadata public USDTInterface;\r
IERC20Metadata public USDCInterface;\r
Aggregator internal aggregatorInterface;\r
\r
mapping(uint256 => bool) public paused;\r
mapping(uint256 => PresaleData) public presale;\r
mapping(uint256 => VestingData) public vesting;\r
mapping(address => mapping(uint256 => UserData)) public userClaimData;\r
mapping(address => bool) public isExcludeMinToken;\r
mapping(address => bool) public isBlackList;\r
mapping(address => bool) public isExist;\r
mapping(address => bool) private isInList;\r
\r
uint256 public MinTokenTobuy;\r
uint256 public currentSale;\r
address public SaleToken;\r
\r
event PresaleCreated(\r
uint256 indexed _id,\r
uint256 _totalTokens,\r
uint256 _startTime,\r
uint256 _endTime\r
);\r
\r
event PresaleUpdated(\r
bytes32 indexed key,\r
uint256 prevValue,\r
uint256 newValue,\r
uint256 timestamp\r
);\r
\r
event TokensBought(\r
address indexed user,\r
uint256 indexed id,\r
address indexed purchaseToken,\r
uint256 tokensBought,\r
uint256 amountPaid,\r
uint256 timestamp\r
);\r
\r
event TokensClaimed(\r
address indexed user,\r
uint256 indexed id,\r
uint256 amount,\r
uint256 timestamp\r
);\r
\r
event PresaleTokenAddressUpdated(\r
address indexed prevValue,\r
address indexed newValue,\r
uint256 timestamp\r
);\r
\r
event PresalePaused(uint256 indexed id, uint256 timestamp);\r
event PresaleUnpaused(uint256 indexed id, uint256 timestamp);\r
\r
constructor(\r
address _oracle,\r
address _usdt,\r
address _usdc,\r
address _SaleToken,\r
uint256 _MinTokenTobuy\r
) {\r
aggregatorInterface = Aggregator(_oracle);\r
SaleToken = _SaleToken;\r
MinTokenTobuy = _MinTokenTobuy;\r
USDTInterface = IERC20Metadata(_usdt);\r
USDCInterface = IERC20Metadata(_usdc);\r
ETH_MULTIPLIER = (10 ** 18);\r
USDT_MULTIPLIER = (10 ** 6);\r
fundReceiver = msg.sender;\r
}\r
\r
function createPresale(\r
uint256 _price,\r
uint256 _nextStagePrice,\r
uint256 _tokensToSell,\r
uint256 _UsdtHardcap\r
) external onlyOwner {\r
require(_price > 0, "Zero price");\r
require(_tokensToSell > 0, "Zero tokens to sell");\r
\r
presaleId++;\r
\r
presale[presaleId] = PresaleData(\r
0,\r
0,\r
_price,\r
_nextStagePrice,\r
0,\r
_tokensToSell,\r
_UsdtHardcap,\r
0,\r
false,\r
false\r
);\r
\r
emit PresaleCreated(presaleId, _tokensToSell, 0, 0);\r
}\r
\r
function setPresaleStage(uint256 _id) public onlyOwner {\r
require(presale[_id].tokensToSell > 0, "Presale don't exist");\r
if (currentSale != 0) {\r
presale[currentSale].endTime = block.timestamp;\r
presale[currentSale].Active = false;\r
}\r
presale[_id].startTime = block.timestamp;\r
presale[_id].Active = true;\r
currentSale = _id;\r
}\r
\r
function setPresaleVesting(\r
uint256[] memory _id,\r
uint256[] memory vestingStartTime,\r
uint256[] memory _initialClaimPercent,\r
uint256[] memory _vestingTime,\r
uint256[] memory _vestingPercentage\r
) public onlyOwner {\r
for (uint256 i = 0; i < _id.length; i++) {\r
vesting[_id[i]] = VestingData(\r
vestingStartTime[i],\r
_initialClaimPercent[i],\r
_vestingTime[i],\r
_vestingPercentage[i],\r
(1000 - _initialClaimPercent[i]) / _vestingPercentage[i]\r
);\r
}\r
}\r
\r
function updatePresaleVesting(\r
uint256 _id,\r
uint256 _vestingStartTime,\r
uint256 _initialClaimPercent,\r
uint256 _vestingTime,\r
uint256 _vestingPercentage\r
) public onlyOwner {\r
vesting[_id].vestingStartTime = _vestingStartTime;\r
vesting[_id].initialClaimPercent = _initialClaimPercent;\r
vesting[_id].vestingTime = _vestingTime;\r
vesting[_id].vestingPercentage = _vestingPercentage;\r
vesting[_id].totalClaimCycles =\r
(100 - _initialClaimPercent) /\r
_vestingPercentage;\r
}\r
\r
uint256 initialClaimPercent;\r
uint256 vestingTime;\r
uint256 vestingPercentage;\r
uint256 totalClaimCycles;\r
\r
function enableClaim(uint256 _id, bool _status) public onlyOwner {\r
presale[_id].isEnableClaim = _status;\r
}\r
\r
function updatePresale(\r
uint256 _id,\r
uint256 _price,\r
uint256 _nextStagePrice,\r
uint256 _tokensToSell,\r
uint256 _Hardcap,\r
bool isclaimAble\r
) external onlyOwner {\r
require(_price > 0, "Zero price");\r
require(_tokensToSell > 0, "Zero tokens to sell");\r
require(_Hardcap > 0, "Zero harcap");\r
presale[_id].price = _price;\r
presale[_id].nextStagePrice = _nextStagePrice;\r
presale[_id].tokensToSell = _tokensToSell;\r
presale[_id].UsdtHardcap = _Hardcap;\r
presale[_id].isEnableClaim = isclaimAble;\r
}\r
\r
function changeFundWallet(address _wallet) external onlyOwner {\r
require(_wallet != address(0), "Invalid parameters");\r
fundReceiver = _wallet;\r
}\r
\r
function changeUSDTToken(address _newAddress) external onlyOwner {\r
require(_newAddress != address(0), "Zero token address");\r
USDTInterface = IERC20Metadata(_newAddress);\r
}\r
\r
function changeUSDCToken(address _newAddress) external onlyOwner {\r
require(_newAddress != address(0), "Zero token address");\r
USDCInterface = IERC20Metadata(_newAddress);\r
}\r
\r
function pausePresale(uint256 _id) external checkPresaleId(_id) onlyOwner {\r
require(!paused[_id], "Already paused");\r
paused[_id] = true;\r
emit PresalePaused(_id, block.timestamp);\r
}\r
\r
function unPausePresale(\r
uint256 _id\r
) external checkPresaleId(_id) onlyOwner {\r
require(paused[_id], "Not paused");\r
paused[_id] = false;\r
emit PresaleUnpaused(_id, block.timestamp);\r
}\r
\r
function getLatestPrice() public view returns (uint256) {\r
(, int256 price, , , ) = aggregatorInterface.latestRoundData();\r
price = (price * (10 ** 10));\r
return uint256(price);\r
}\r
\r
modifier checkPresaleId(uint256 _id) {\r
require(_id > 0 && _id == currentSale, "Invalid presale id");\r
_;\r
}\r
\r
modifier checkSaleState(uint256 _id, uint256 amount) {\r
require(presale[_id].Active == true, "preSAle not Active");\r
require(\r
amount > 0 &&\r
amount <= presale[_id].tokensToSell - presale[_id].Sold,\r
"Invalid sale amount"\r
);\r
_;\r
}\r
\r
function ExcludeAccouctFromMinBuy(\r
address _user,\r
bool _status\r
) external onlyOwner {\r
isExcludeMinToken[_user] = _status;\r
}\r
\r
function buyWithUSDT(\r
uint256 usdAmount\r
)\r
external\r
checkPresaleId(currentSale)\r
checkSaleState(currentSale, usdtToTokens(currentSale, usdAmount))\r
nonReentrant\r
returns (bool)\r
{\r
require(!paused[currentSale], "Presale paused");\r
require(\r
presale[currentSale].Active == true,\r
"Presale is not active yet"\r
);\r
require(!isBlackList[msg.sender], "Account is blackListed");\r
require(\r
presale[currentSale].amountRaised + usdAmount <=\r
presale[currentSale].UsdtHardcap,\r
"Amount should be less than leftHardcap"\r
);\r
if (!isExist[msg.sender]) {\r
isExist[msg.sender] = true;\r
uniqueBuyers++;\r
\r
if (!isInList[msg.sender]) {\r
participantsList.push(msg.sender);\r
isInList[msg.sender] = true;\r
}\r
}\r
uint256 tokens = usdtToTokens(currentSale, usdAmount);\r
presale[currentSale].Sold += tokens;\r
presale[currentSale].amountRaised += usdAmount;\r
overalllRaised += usdAmount;\r
\r
if (isExcludeMinToken[msg.sender] == false) {\r
require(tokens >= MinTokenTobuy, "Less than min amount");\r
}\r
if (userClaimData[_msgSender()][currentSale].claimAbleAmount > 0) {\r
userClaimData[_msgSender()][currentSale].claimAbleAmount += tokens;\r
userClaimData[_msgSender()][currentSale]\r
.investedAmount += usdAmount;\r
} else {\r
userClaimData[_msgSender()][currentSale] = UserData(\r
usdAmount,\r
0,\r
tokens,\r
0,\r
0,\r
0,\r
0\r
);\r
}\r
\r
uint256 ourAllowance = USDTInterface.allowance(\r
_msgSender(),\r
address(this)\r
);\r
require(usdAmount <= ourAllowance, "Make sure to add enough allowance");\r
(bool success, ) = address(USDTInterface).call(\r
abi.encodeWithSignature(\r
"transferFrom(address,address,uint256)",\r
_msgSender(),\r
fundReceiver,\r
usdAmount\r
)\r
);\r
require(success, "Token payment failed");\r
emit TokensBought(\r
_msgSender(),\r
currentSale,\r
address(USDTInterface),\r
tokens,\r
usdAmount,\r
block.timestamp\r
);\r
return true;\r
}\r
\r
function changeClaimAddress(\r
address _oldAddress,\r
address _newWallet\r
) public onlyOwner {\r
for (uint256 i = 1; i < presaleId; i++) {\r
require(isExist[_oldAddress], "User not a participant");\r
userClaimData[_newWallet][i].claimAbleAmount = userClaimData[\r
_oldAddress\r
][i].claimAbleAmount;\r
userClaimData[_oldAddress][i].claimAbleAmount = 0;\r
}\r
isExist[_oldAddress] = false;\r
isExist[_newWallet] = true;\r
}\r
\r
function blackListUser(address _user, bool _value) public onlyOwner {\r
isBlackList[_user] = _value;\r
}\r
\r
function buyWithUSDC(\r
uint256 usdcAmount\r
)\r
external\r
checkPresaleId(currentSale)\r
checkSaleState(currentSale, usdtToTokens(currentSale, usdcAmount))\r
nonReentrant\r
returns (bool)\r
{\r
require(!paused[currentSale], "Presale paused");\r
require(\r
presale[currentSale].Active == true,\r
"Presale is not active yet"\r
);\r
require(\r
presale[currentSale].amountRaised + usdcAmount <=\r
presale[currentSale].UsdtHardcap,\r
"Amount should be less than leftHardcap"\r
);\r
require(!isBlackList[msg.sender], "Account is blackListed");\r
if (!isExist[msg.sender]) {\r
isExist[msg.sender] = true;\r
uniqueBuyers++;\r
}\r
uint256 tokens = usdtToTokens(currentSale, usdcAmount);\r
presale[currentSale].Sold += tokens;\r
presale[currentSale].amountRaised += usdcAmount;\r
overalllRaised += usdcAmount;\r
\r
if (isExcludeMinToken[msg.sender] == false) {\r
require(tokens >= MinTokenTobuy, "Less than min amount");\r
}\r
if (userClaimData[_msgSender()][currentSale].claimAbleAmount > 0) {\r
userClaimData[_msgSender()][currentSale].claimAbleAmount += tokens;\r
userClaimData[_msgSender()][currentSale]\r
.investedAmount += usdcAmount;\r
} else {\r
userClaimData[_msgSender()][currentSale] = UserData(\r
usdcAmount,\r
0,\r
tokens,\r
0,\r
0,\r
0,\r
0\r
);\r
require(isExist[_msgSender()], "User not a participant");\r
}\r
\r
uint256 ourAllowance = USDTInterface.allowance(\r
_msgSender(),\r
address(this)\r
);\r
require(\r
usdcAmount <= ourAllowance,\r
"Make sure to add enough allowance"\r
);\r
(bool success, ) = address(USDCInterface).call(\r
abi.encodeWithSignature(\r
"transferFrom(address,address,uint256)",\r
_msgSender(),\r
fundReceiver,\r
usdcAmount\r
)\r
);\r
require(success, "Token payment failed");\r
emit TokensBought(\r
_msgSender(),\r
currentSale,\r
address(USDTInterface),\r
tokens,\r
usdcAmount,\r
block.timestamp\r
);\r
return true;\r
}\r
\r
function buyWithEth()\r
external\r
payable\r
checkPresaleId(currentSale)\r
checkSaleState(currentSale, ethToTokens(currentSale, msg.value))\r
nonReentrant\r
returns (bool)\r
{\r
uint256 usdAmount = (msg.value * getLatestPrice() * USDT_MULTIPLIER) /\r
(ETH_MULTIPLIER * ETH_MULTIPLIER);\r
require(\r
presale[currentSale].amountRaised + usdAmount <=\r
presale[currentSale].UsdtHardcap,\r
"Amount should be less than leftHardcap"\r
);\r
require(!isBlackList[msg.sender], "Account is blackListed");\r
require(!paused[currentSale], "Presale paused");\r
require(\r
presale[currentSale].Active == true,\r
"Presale is not active yet"\r
);\r
if (!isExist[msg.sender]) {\r
isExist[msg.sender] = true;\r
uniqueBuyers++;\r
}\r
\r
uint256 tokens = usdtToTokens(currentSale, usdAmount);\r
if (isExcludeMinToken[msg.sender] == false) {\r
require(tokens >= MinTokenTobuy, "Insufficient amount!");\r
}\r
presale[currentSale].Sold += tokens;\r
presale[currentSale].amountRaised += usdAmount;\r
overalllRaised += usdAmount;\r
\r
if (userClaimData[_msgSender()][currentSale].claimAbleAmount > 0) {\r
userClaimData[_msgSender()][currentSale].claimAbleAmount += tokens;\r
userClaimData[_msgSender()][currentSale]\r
.investedAmount += usdAmount;\r
} else {\r
userClaimData[_msgSender()][currentSale] = UserData(\r
usdAmount,\r
0, // Last claimed at\r
tokens, // total tokens to be claimed\r
0, // vesting claimed amount\r
0, // claimed amount\r
0, // claim count\r
0 // vesting percent\r
);\r
}\r
\r
sendValue(payable(fundReceiver), msg.value);\r
emit TokensBought(\r
_msgSender(),\r
currentSale,\r
address(0),\r
tokens,\r
msg.value,\r
block.timestamp\r
);\r
return true;\r
}\r
\r
function ethBuyHelper(\r
uint256 _id,\r
uint256 amount\r
) external view returns (uint256 ethAmount) {\r
uint256 usdPrice = (amount * presale[_id].price);\r
ethAmount =\r
(usdPrice * ETH_MULTIPLIER) /\r
(getLatestPrice() * 10 ** IERC20Metadata(SaleToken).decimals());\r
}\r
\r
function usdtBuyHelper(\r
uint256 _id,\r
uint256 amount\r
) external view returns (uint256 usdPrice) {\r
usdPrice =\r
(amount * presale[_id].price) /\r
10 ** IERC20Metadata(SaleToken).decimals();\r
}\r
\r
function ethToTokens(\r
uint256 _id,\r
uint256 amount\r
) public view returns (uint256 _tokens) {\r
uint256 usdAmount = (amount * getLatestPrice() * USDT_MULTIPLIER) /\r
(ETH_MULTIPLIER * ETH_MULTIPLIER);\r
_tokens = usdtToTokens(_id, usdAmount);\r
}\r
\r
function usdtToTokens(\r
uint256 _id,\r
uint256 amount\r
) public view returns (uint256 _tokens) {\r
_tokens = (amount * presale[_id].price) / USDT_MULTIPLIER;\r
}\r
\r
function sendValue(address payable recipient, uint256 amount) internal {\r
require(address(this).balance >= amount, "Low balance");\r
(bool success, ) = recipient.call{value: amount}("");\r
require(success, "ETH Payment failed");\r
}\r
\r
function claimableAmount(\r
address user,\r
uint256 _id\r
) public view returns (uint256) {\r
UserData memory _user = userClaimData[user][_id];\r
\r
require(_user.claimAbleAmount > 0, "Nothing to claim");\r
uint256 amount = _user.claimAbleAmount;\r
require(amount > 0, "Already claimed");\r
return amount;\r
}\r
\r
function claimMultiple() public {\r
for (uint8 i = 1; i <= presaleId; i++) {\r
if (\r
userClaimData[msg.sender][i].claimAbleAmount > 0 &&\r
block.timestamp > vesting[i].vestingStartTime\r
) {\r
claim(msg.sender, i);\r
}\r
}\r
}\r
\r
function claimAmount(uint256 _id) public {\r
claim(msg.sender, _id);\r
}\r
\r
function claim(address _user, uint256 _id) internal returns (bool) {\r
require(isExist[_msgSender()], "User not a participant");\r
uint256 amount = claimableAmount(_user, _id);\r
require(amount > 0, "No claimable amount");\r
require(!isBlackList[_user], "Account is blackListed");\r
require(SaleToken != address(0), "Presale token address not set");\r
require(\r
amount <= IERC20(SaleToken).balanceOf(address(this)),\r
"Not enough tokens in the contract"\r
);\r
require((presale[_id].isEnableClaim == true), "Claim is not enable");\r
require(\r
block.timestamp > vesting[_id].vestingStartTime,\r
"Vesting time is not started yet"\r
);\r
uint256 transferAmount;\r
if (userClaimData[_user][_id].claimCount == 0) {\r
transferAmount =\r
(amount * (vesting[_id].initialClaimPercent)) /\r
1000;\r
userClaimData[_user][_id].activePercentAmount =\r
(amount * vesting[_id].vestingPercentage) /\r
1000;\r
bool status = IERC20(SaleToken).transfer(_user, transferAmount);\r
require(status, "Token transfer failed");\r
userClaimData[_user][_id].claimAbleAmount -= transferAmount;\r
userClaimData[_user][_id].claimedAmount += transferAmount;\r
userClaimData[_user][_id].claimCount++;\r
} else if (\r
userClaimData[_user][_id].claimAbleAmount >\r
userClaimData[_user][_id].activePercentAmount\r
) {\r
uint256 duration = block.timestamp - vesting[_id].vestingStartTime;\r
uint256 multiplier = duration / vesting[_id].vestingTime;\r
if (multiplier > vesting[_id].totalClaimCycles) {\r
multiplier = vesting[_id].totalClaimCycles;\r
}\r
uint256 _amount = multiplier *\r
userClaimData[_user][_id].activePercentAmount;\r
transferAmount =\r
_amount -\r
userClaimData[_user][_id].claimedVestingAmount;\r
require(transferAmount > 0, "Please wait till next claim");\r
bool status = IERC20(SaleToken).transfer(_user, transferAmount);\r
require(status, "Token transfer failed");\r
userClaimData[_user][_id].claimAbleAmount -= transferAmount;\r
userClaimData[_user][_id].claimedVestingAmount += transferAmount;\r
userClaimData[_user][_id].claimedAmount += transferAmount;\r
userClaimData[_user][_id].claimCount++;\r
} else {\r
uint256 duration = block.timestamp - vesting[_id].vestingStartTime;\r
uint256 multiplier = duration / vesting[_id].vestingTime;\r
if (multiplier > vesting[_id].totalClaimCycles + 1) {\r
transferAmount = userClaimData[_user][_id].claimAbleAmount;\r
require(transferAmount > 0, "Please wait till next claim");\r
bool status = IERC20(SaleToken).transfer(_user, transferAmount);\r
require(status, "Token transfer failed");\r
userClaimData[_user][_id].claimAbleAmount -= transferAmount;\r
userClaimData[_user][_id].claimedAmount += transferAmount;\r
userClaimData[_user][_id]\r
.claimedVestingAmount += transferAmount;\r
userClaimData[_user][_id].claimCount++;\r
} else {\r
revert("Wait for next claiim");\r
}\r
}\r
return true;\r
}\r
\r
function WithdrawTokens(address _token, uint256 amount) external onlyOwner {\r
IERC20(_token).transfer(fundReceiver, amount);\r
}\r
\r
function WithdrawContractFunds(uint256 amount) external onlyOwner {\r
sendValue(payable(fundReceiver), amount);\r
}\r
\r
function ChangeTokenToSell(address _token) public onlyOwner {\r
SaleToken = _token;\r
}\r
\r
function ChangeMinTokenToBuy(uint256 _amount) public onlyOwner {\r
MinTokenTobuy = _amount;\r
}\r
\r
function ChangeOracleAddress(address _oracle) public onlyOwner {\r
aggregatorInterface = Aggregator(_oracle);\r
}\r
\r
function blockTimeStamp() public view returns (uint256) {\r
return block.timestamp;\r
}\r
\r
struct ExportUserData {\r
address user;\r
uint256 totalInvestedAmount;\r
uint256 totalClaimableAmount;\r
}\r
\r
function getExportData(\r
address[] memory _users\r
) external view onlyOwner returns (ExportUserData[] memory) {\r
ExportUserData[] memory exportData = new ExportUserData[](\r
_users.length\r
);\r
\r
for (uint256 i = 0; i < _users.length; i++) {\r
address user = _users[i];\r
uint256 totalInvested = 0;\r
uint256 totalClaimable = 0;\r
\r
// Sum across all presale stages\r
for (uint256 j = 1; j <= presaleId; j++) {\r
totalInvested += userClaimData[user][j].investedAmount;\r
totalClaimable += userClaimData[user][j].claimAbleAmount;\r
}\r
\r
exportData[i] = ExportUserData({\r
user: user,\r
totalInvestedAmount: totalInvested,\r
totalClaimableAmount: totalClaimable\r
});\r
}\r
\r
return exportData;\r
}\r
\r
function getAllParticipants()\r
external\r
view\r
onlyOwner\r
returns (address[] memory)\r
{\r
return participantsList;\r
}\r
\r
function getUserSummary(\r
address _user\r
)\r
external\r
view\r
returns (\r
uint256 totalInvested,\r
uint256 totalClaimable,\r
uint256 stagesParticipated\r
)\r
{\r
uint256 stages = 0;\r
\r
for (uint256 i = 1; i <= presaleId; i++) {\r
if (userClaimData[_user][i].claimAbleAmount > 0) {\r
totalInvested += userClaimData[_user][i].investedAmount;\r
totalClaimable += userClaimData[_user][i].claimAbleAmount;\r
stages++;\r
}\r
}\r
\r
return (totalInvested, totalClaimable, stages);\r
}\r
}\r
"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 1000
},
"evmVersion": "paris",
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-10-16 11:18:08
Comments
Log in to comment.
No comments yet.