// SPDX-License-Identifier: Unlicensed
// Boys Club On Base: Meet Brett, Landwolf, Andy and Pepe all in one token! $BLAP
// TG: t.me/boysclubBLAP
// Web: https://boys-club-on-base.com/
pragma solidity 0.8.24;
// Abstract contract for handling msg.sender in a secure way
abstract contract Context {
// Internal function to get the current message sender
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
// Contract for ownership management
contract Ownable is Context {
// Private state variable to store the owner's address
address private _owner;
// Event to notify when ownership is transferred
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// Constructor to set the initial owner
constructor () {
address msgSender = _msgSender(); // Get the current sender using Context
_owner = msgSender; // Set the owner
emit OwnershipTransferred(address(0), msgSender); // Emit event for ownership transfer
}
// Public function to check who is the current owner
function owner() public view returns (address) {
return _owner;
}
// Modifier to restrict functions to the current owner
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner"); // Check if the sender is the owner
_; // Continue execution
}
// Function to transfer ownership to a new owner, only callable by the current owner
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address"); // New owner must be a valid address
emit OwnershipTransferred(_owner, newOwner); // Emit ownership transfer event
_owner = newOwner; // Update the owner
}
// Function for the owner to renounce ownership, only callable by the current owner
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0)); // Emit event for renouncing ownership
_owner = address(0); // Reset the owner to zero address
}
}
// Standard interface for ERC20 tokens
interface IERC20 {
// Returns the total token supply
function totalSupply() external view returns (uint256);
// Returns the account balance of another account with address `account`
function balanceOf(address account) external view returns (uint256);
// Transfers `amount` tokens to `recipient`, returns a boolean value indicating success
function transfer(address recipient, uint256 amount) external returns (bool);
// Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner`
function allowance(address owner, address spender) external view returns (uint256);
// Sets `amount` as the allowance of `spender` over the caller’s tokens, returns a boolean value indicating success
function approve(address spender, uint256 amount) external returns (bool);
// Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism, returns a boolean value indicating success
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
// Emitted when `value` tokens are moved from one account (`from`) to another (`to`)
event Transfer(address indexed from, address indexed to, uint256 value);
// Emitted when `owner` sets `amount` as the allowance of `spender` over their tokens
event Approval (address indexed owner, address indexed spender, uint256 value);
}
// Extension of the IERC20 interface that includes metadata about the token
interface IERC20Metadata is IERC20 {
// Returns the name of the token
function name() external view returns (string memory);
// Returns the symbol of the token
function symbol() external view returns (string memory);
// Returns the number of decimals the token uses
function decimals() external view returns (uint8);
}
// ERC20 standard token implementation with additional metadata.
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances; // Mapping of account addresses to their current balance.
mapping(address => mapping(address => uint256)) private _allowances; // Mapping of account addresses to another account's allowance.
uint256 private _totalSupply; // Total supply of tokens.
string private _name; // Token name.
string private _symbol; // Token symbol.
// Constructor to set token name and symbol upon deployment.
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
// Returns the name of the token.
function name() public view virtual override returns (string memory) {
return _name;
}
// Returns the symbol of the token.
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
// Returns the number of decimals used to get its user representation.
function decimals() public view virtual override returns (uint8) {
return 18; // Standard decimal count in Ethereum for tokens.
}
// Returns the total token supply.
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
// Returns the balance of the account with address `account`.
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
// Transfers `amount` tokens to `recipient`, returns true if successful.
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount); // Internal function call to handle token transfer.
return true;
}
// Returns the allowance from `owner` to `spender`.
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
// Approves `spender` to spend `amount` tokens on behalf of the caller.
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
// Transfers `amount` tokens from `sender` to `recipient`, considering the allowance.
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount); // Call internal transfer function.
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount); // Update allowance accordingly.
}
return true;
}
// Increases the allowance granted to `spender` by the caller.
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
// Decreases the allowance granted to `spender` by the caller.
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue); // Safely update the allowance.
}
return true;
}
// Handles the token transfer logic; only callable internally
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address"); // Prevent transferring from the zero address
require(recipient != address(0), "ERC20: transfer to the zero address"); // Prevent transferring to the zero address
_beforeTokenTransfer(sender, recipient, amount); // Hook to perform actions before the transfer
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); // Check if sender has enough tokens
unchecked {
_balances[sender] = senderBalance - amount; // Deduct the amount from sender
}
_balances[recipient] += amount; // Add the amount to recipient
emit Transfer(sender, recipient, amount); // Emit a transfer event
_afterTokenTransfer(sender, recipient, amount); // Hook to perform actions after the transfer
}
// Creates total supply and assigns it to an account, only callable internally
function _createInitialSupply(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: _mint to the zero address"); // Prevent minting to the zero address
_beforeTokenTransfer(address(0), account, amount); // Hook to perform actions before minting
_totalSupply += amount; // Increase total supply
_balances[account] += amount; // Add new tokens to account balance
emit Transfer(address(0), account, amount); // Emit a minting event
_afterTokenTransfer(address(0), account, amount); // Hook to perform actions after minting
}
// Approves another account to spend tokens on behalf of the owner
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address"); // Prevent approving from the zero address
require(spender != address(0), "ERC20: approve to the zero address"); // Prevent approving to the zero address
_allowances[owner][spender] = amount; // Set the allowance
emit Approval(owner, spender, amount); // Emit an approval event
}
// Hook that is called before any transfer of tokens; can be overridden
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
// Hook that is called after any transfer of tokens; can be overridden
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// Interface for interacting with the Uniswap V2 Factory contract
interface IUniswapV2Factory {
// Creates a liquidity pair for two tokens and returns the address of the pair
function createPair(address tokenA, address tokenB) external returns (address pair);
}
// Interface for the Uniswap V2 Router02
interface IUniswapV2Router02 {
// Returns the address of the Uniswap V2 Factory
function factory() external pure returns (address);
// Returns the address of the WETH contract
function WETH() external pure returns (address);
}
contract BoysClub is ERC20, Ownable {
IUniswapV2Router02 public uniswapV2Router; // Uniswap V2 router interface
address public immutable uniswapV2Pair; // Uniswap pair address for this token
uint256 public _maxWalletToken = 1000000000 * (10**18); // Max tokens that a wallet can hold
// Mapping to exclude addresses from max wallet limit
mapping (address => bool) private _isExcludedFromWalletLimit;
// Event to indicate exclusion from wallet limit
event ExcludeFromWalletLimit(address indexed account, bool isExcluded);
// Constructor to initialize the token with Uniswap router and pair
constructor() ERC20("Boys Club", "BLAP") {
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24);
// Create a uniswap pair for this new token
address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
uniswapV2Router = _uniswapV2Router;
uniswapV2Pair = _uniswapV2Pair;
// Initial token supply creation, only called here and never again
_createInitialSupply(owner(), 1000000000 * (10**18));
}
// Overridden _transfer function with custom logic for max wallet
function _transfer(
address from,
address to,
uint256 amount
) internal override {
require(from != address(0), "ERC20: transfer from the zero address"); // Ensure not transferring from zero address
require(to != address(0), "ERC20: transfer to the zero address"); // Ensure not transferring to zero address
// If the amount is zero, perform the transfer normally and return
if(amount == 0) {
super._transfer(from, to, 0);
return;
}
// Enforce max wallet token amount if not excluded
if(from == uniswapV2Pair && !_isExcludedFromWalletLimit[from] && !_isExcludedFromWalletLimit[to]) {
uint256 contractBalanceRecepient = balanceOf(to);
require(contractBalanceRecepient + amount <= _maxWalletToken, "Exceeds maximum wallet token amount.");
}
super._transfer(from, to, amount);
}
// Allow only the owner to exclude an account from wallet limit
function excludeFromMaxWallet(address account, bool value) public onlyOwner {
_isExcludedFromWalletLimit[account] = value; // Set the wallet limit exclusion status
emit ExcludeFromWalletLimit(account, value); // Emit an event when the status changes
}
// Set the maximum token amount that a wallet can hold
function setMaxWalletLimit(uint256 _newLimit) public onlyOwner {
// Validation to ensure the new limit isn't too small
require(_newLimit >= totalSupply() / 100, "Max wallet limit must be at least 1% of total supply");
_maxWalletToken = _newLimit; // Update the maximum wallet token limit
}
}
{
"compilationTarget": {
"BoysClub.sol": "BoysClub"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromWalletLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_maxWalletToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"excludeFromMaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLimit","type":"uint256"}],"name":"setMaxWalletLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"}]