Skip to content

Instantly share code, notes, and snippets.

Last active January 10, 2024 13:25
Show Gist options
  • Save coderwithsense/781f82b6f5129cc969a25079ac3ebadb to your computer and use it in GitHub Desktop.
Save coderwithsense/781f82b6f5129cc969a25079ac3ebadb to your computer and use it in GitHub Desktop.
CryptoGrad PreSale Smart Contract (Editing required for production ready)

TokenPresale Smart Contract


The TokenPresale smart contract facilitates the sale of a specific ERC-20 token at a predetermined rate in exchange for Ether (ETH). It includes features such as pausing, ownership control, and a cap on the total ETH that can be raised during the presale.

Important Variables

  • token: The ERC-20 token being sold.
  • rate: The rate at which tokens are exchanged for ETH, denominated in wei.
  • cap: The maximum amount of ETH that can be raised during the presale.
  • weiRaised: Total amount of ETH raised so far.
  • tokenAddress: The address of the ERC-20 token contract.
  • tokensPurchased: Mapping to keep track of the amount of tokens purchased by each beneficiary.
  • claimedAmount: Mapping to track the amount of tokens claimed by each beneficiary.



Description: Constructor to initialize the smart contract with the token rate and cap. Parameters:

  • _rate: Token rate per ETH (wei).
  • _cap: Cap in ETH (wei).


Description: Allows users to purchase tokens by sending ETH to the contract. Parameters:

  • beneficiary: The address that will receive the purchased tokens.


Description: Provides an estimate of the number of tokens a user can buy with a specific amount of ETH. Parameters:

  • _weiAmount: The amount of ETH in wei.


Description: Allows users to claim their purchased tokens.


Description: Allows the owner to withdraw the ETH balance from the contract.


Description: Allows the owner to pause the presale.


Description: Allows the owner to unpause the presale.


Description: Returns the number of tokens available for sale in the contract.


Description: Fallback function to allow users to send ETH and purchase tokens.




  • purchaser: The address that initiated the token purchase.
  • beneficiary: The address that will receive the purchased tokens.
  • value: The amount of ETH sent.
  • amount: The amount of tokens purchased.



  • beneficiary: The address that claimed the tokens.
  • amount: The amount of tokens claimed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
contract TokenPresale is Ownable, Pausable {
using SafeMath for uint256;
IERC20 public token; // The token being sold
uint256 public rate; // Token rate per ETH (wei)
uint256 public cap; // Cap in ETH (wei)
uint256 public weiRaised;
address public tokenAddress = 0x032ACfAFb4Ffa8acb556e4b7535Ee542bc152726;
mapping(address => uint256) private tokensPurchased;
mapping(address => uint256) public claimedAmount;
event TokenPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
event TokenClaimed(address indexed beneficiary, uint256 amount);
constructor(uint256 _rate, uint256 _cap) Ownable(msg.sender) {
require(_rate > 0, "Token rate must be greater than zero");
require(_cap > 0, "Cap must be greter than zero");
token = IERC20(tokenAddress);
rate = _rate;
cap = _cap;
function buyToken(address beneficiary) public payable whenNotPaused {
uint256 weiAmount = msg.value;
require(weiAmount > 0, "Wei amount must be greater than zero");
require(weiRaised.add(weiAmount) <= cap, "Cap exceeded");
uint256 tokenAmount = getTokenAmount(weiAmount);
require(tokenAmount > 0, "Token amount must be greater than zero");
require(tokensAvailableForSale() >= tokenAmount, "Not enough tokens available");
token.transfer(beneficiary, tokenAmount);
tokensPurchased[beneficiary] = tokensPurchased[beneficiary].add(tokenAmount);
weiRaised = weiRaised.add(weiAmount);
emit TokenPurchased(msg.sender, beneficiary, weiAmount, tokenAmount);
function estimateTokenBuy(uint256 _weiAmount) public view returns (uint256) {
return getTokenAmount(_weiAmount);
function getTokenAmount(uint256 _weiAmount) private view returns (uint256){
return _weiAmount.mul(rate);
function getClaimableAmount(address _userAddress) public view returns (uint256) {
uint256 purchasedTokens = tokensPurchased[_userAddress];
uint256 claimed = claimedAmount[_userAddress];
if(purchasedTokens > claimed){
return purchasedTokens.sub(claimed);
} else {
return 0;
function claim() public whenNotPaused {
uint256 claimable = getClaimableAmount(msg.sender);
require(claimable > 0, "No tokens to claim");
claimedAmount[msg.sender] = claimedAmount[msg.sender].add(claimable);
token.transfer(msg.sender, claimable);
emit TokenClaimed(msg.sender, claimable);
function withdraw() external onlyOwner {
function pausePresale() public onlyOwner{
function unPausePresale() public onlyOwner{
function tokensAvailableForSale() public view returns(uint256){
return token.balanceOf(address(this));
receive() external payable whenNotPaused {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment