Contract Source Code:
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
/// @title IERC20 Token Standard
/// @notice Interface for the ERC20 standard token contract
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
/// @title Interface for UniswapV2Factory Contract
/// @notice It is used to create new instances of pairs
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB)
external
returns (address pair);
}
/// @title Interface for UniswapV2Router02 Contract
/// @notice It is used to get information about liquidity reserves
interface IUniswapV2Router {
function factory() external pure returns (address);
function WETH() external pure returns (address);
}
/// @author Kenji Sato
/// @title Hakkaido Token Contract
/// @notice Hokkaido token is a utility token created for use on the Hokkaido platform,
/// acting as an intermediary between the user's token and Uniswap pool.
/// It implements the IERC20 token standard.
/// @custom:website https://www.hokkaido.ai
/// @custom:telegram https://t.me/hokk_token
/// @custom:twitter https://twitter.com/hokk_token
contract Hokkaido is IERC20 {
// Address of the owner of the contract
address public owner;
// Total supply of the token
uint256 public totalSupply;
// Mapping of account addresses to their respective balances
mapping(address => uint256) public balances;
// Mapping of holder addresses to a mapping of spender addresses to their respective allowances
mapping(address => mapping(address => uint256)) public allowances;
// The timestamp when the time lock for purchasing tokens ends
// This is an anti-sniping bot measure to prevent purchases from the Uniswap during the specified time frame
uint256 public purchaseTimeLockEnd;
// The maximum number of tokens that a wallet can hold
// This is a measure to prevent price manipulation
// The maxWallet restriction will be removed after 24 hours from allowing trading
uint256 public maxWallet;
// The timestamp indicating the end time of the period during
// which a maximum wallet size is enforced
uint256 public maxWalletEndTime;
// The Uniswap V2 router contract
IUniswapV2Router public uniswapV2Router;
// The address of the Uniswap V2 liquidity pool for the token
address public uniswapV2Pair;
// Constants for token name, symbol and decimals
string private constant NAME = "Hokkaido";
string private constant SYMBOL = "HOKK";
uint8 private constant DECIMALS = 18;
// Event for transferring ownership of the contract
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
// Modifier to only allow the contract owner to execute a function
modifier onlyOwner() {
require(msg.sender == owner, "Error: Caller is not the contract owner");
_;
}
// Contract constructor
constructor(uint256 amount, uint256 timelock) {
// Create a new instance of IUniswapV2Router
IUniswapV2Router _uniswapV2Router = IUniswapV2Router(
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
);
// Assign the new instance to the uniswapV2Router variable
uniswapV2Router = _uniswapV2Router;
// Create a new Uniswap pair for this new token
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
// Assign the time lock for purchasing tokens
purchaseTimeLockEnd = timelock;
// Assign the end time of the period during which a maximum wallet size is enforced
maxWalletEndTime = purchaseTimeLockEnd + 24 hours;
// Assign the totalSupply to the given amount
totalSupply = amount;
// Assign the maxWallet to 2% of the totalSupply
maxWallet = (totalSupply * 2) / 100;
// Assign the full amount to the balance of the contract creator
balances[msg.sender] = totalSupply;
// Emit a Transfer event from address 0 to the contract creator with the totalSupply as the value
emit Transfer(address(0), msg.sender, totalSupply);
// Set the owner to the contract creator
owner = msg.sender;
}
/**
* @dev Returns the balance of the specified address.
* @param account The address to retrieve the balance of.
* @return The balance of the specified address.
*/
function balanceOf(address account)
external
view
override
returns (uint256)
{
return balances[account];
}
/**
* @dev Returns the allowance of a spender for a given holder.
* @param holder The address of the holder.
* @param spender The address of the spender.
* @return The allowance of the spender for the given holder.
*/
function allowance(address holder, address spender)
external
view
override
returns (uint256)
{
return allowances[holder][spender];
}
/**
* @dev Returns the name of the token.
* @return string memory The name of the token.
*/
function name() external pure returns (string memory) {
return NAME;
}
/**
* @dev Returns the symbol of the token.
* @return string memory The symbol of the token.
*/
function symbol() external pure returns (string memory) {
return SYMBOL;
}
/**
* @dev Returns the number of decimal places used to represent the token amount.
* @return uint8 The number of decimal places used to represent the token amount.
*/
function decimals() external pure returns (uint8) {
return DECIMALS;
}
/**
* @dev Approves the given spender to transfer the specified amount from the msg.sender's account.
* @param spender The address of the spender to approve.
* @param amount The amount of token to be approved for transfer.
* @return bool True if the approval was successful.
*/
function approve(address spender, uint256 amount)
external
virtual
override
returns (bool)
{
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
/**
* @dev Renounces ownership of the contract.
*/
function renounceOwnership() external virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers the specified amount of tokens from the sender to the recipient on behalf of the sender.
* @param sender The address of the token holder to transfer from.
* @param recipient The address of the recipient to transfer to.
* @param amount The amount of token to be transferred.
* @return bool True if the transfer was successful.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external override returns (bool) {
// Check if the allowance is sufficient
require(
allowances[sender][msg.sender] >= amount,
"Error: insufficient allowance."
);
// Decrease the allowance
allowances[sender][msg.sender] -= amount;
return _transfer(sender, recipient, amount);
}
/**
* @dev Transfers the specified amount of tokens from the msg.sender's account to the recipient.
* @param recipient The address of the recipient to transfer to.
* @param amount The amount of token to be transferred.
* @return bool True if the transfer was successful.
*/
function transfer(address recipient, uint256 amount)
external
override
returns (bool)
{
return _transfer(msg.sender, recipient, amount);
}
/**
* @dev Transfers the ownership of the contract to the new owner.
* @param newOwner The address of the new owner.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = owner;
owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev Transfers `amount` tokens from `sender` to `recipient`.
*
* @param sender The address of the sender.
* @param recipient The address of the recipient.
* @param amount The amount of tokens to transfer.
*
* @return A boolean indicating whether the transfer was successful.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual returns (bool) {
// Ensure that the `sender` and `recipient` addresses are not the zero address
require(
sender != address(0) && recipient != address(0),
"Error: Transfer from/to the zero address is not allowed."
);
// Check the balance of the `sender` to make sure the transfer amount is valid
uint256 senderBalance = balances[sender];
require(
senderBalance >= amount,
"Error: Transfer amount exceeds the sender's balance."
);
// Prevent purchases from the Uniswap during a specified time lock period
// which serves as an anti-sniping bot measure.
if (sender == uniswapV2Pair && block.timestamp < purchaseTimeLockEnd) {
revert(
"Error: Purchase from Uniswap DEX not allowed during timelock period."
);
}
// Check whether the maxWallet restriction is in effect
// and the recipient is not the UniswapV2 pair since we need to add liquidity
if (block.timestamp < maxWalletEndTime && recipient != uniswapV2Pair) {
// Check whether the sum of the recipient's current balance
// and the transferred amount exceeds the maxWallet limit
require(
balances[recipient] + amount <= maxWallet,
"Error: Recipient balance exceeds maximum wallet size."
);
} else if (
block.timestamp >= maxWalletEndTime && maxWalletEndTime != 0
) {
// Remove the maxWallet restriction after the specified time lock period
maxWallet = totalSupply;
maxWalletEndTime = 0;
}
// Perform the transfer
balances[sender] -= amount;
balances[recipient] += amount;
// Emit the Transfer event
emit Transfer(sender, recipient, amount);
// Return true to indicate the transfer was successful
return true;
}
}