Contract Name:
UbuntuToken
Contract Source Code:
<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/**
* @dev Provides information about the current execution context.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./Context.sol";
import "./IERC20Metadata.sol";
/**
* @dev Implementation of the ERC20 interface.
*/
contract ERC20 is Context, IERC20Metadata {
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
address sender = _msgSender();
_transfer(sender, recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address sender = _msgSender();
_approve(sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
address caller = _msgSender();
_spendAllowance(sender, caller, amount);
_transfer(sender, recipient, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address sender = _msgSender();
_approve(sender, spender, _allowances[sender][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address sender = _msgSender();
uint256 currentAllowance = _allowances[sender][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
_approve(sender, spender, currentAllowance - subtractedValue);
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from zero address");
require(recipient != address(0), "ERC20: transfer to zero address");
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to zero address");
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from zero address");
require(spender != address(0), "ERC20: approve to zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./ERC20.sol";
import "./Ownable.sol";
interface IUniswapV2Factory {
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
}
interface IUniswapV2Router02 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
}
/**
* @dev Ubuntu Token Contract with anti-bot and vesting features
* - Anti-bot: 99% tax on bot sells, sent to liquidity pool
* - Vesting: Gradual token release over 18 months starting June 1, 2026
* - Tax applies only on DEX trades (Uniswap)
* - Regular wallet-to-wallet transfers have 0% tax
*/
contract UbuntuToken is ERC20, Ownable {
address public liquidityWallet = address(0xa591f5Fcd9756008918259a60701b4040ff5A676);
uint256 public buyTax = 300; // 3% (300/10000)
uint256 public sellTax = 300; // 3% (300/10000)
uint256 public buyBurn = 2; // 0.02% (2/10000)
uint256 public sellBurn = 2; // 0.02% (2/10000)
uint256 public botTax = 9900; // 99% (9900/10000) for bots
uint256 public constant TAX_DENOMINATOR = 10000;
IUniswapV2Router02 public uniswapV2Router;
address public uniswapV2Pair;
// Addresses exempt from tax
mapping(address => bool) public isExcludedFromFees;
// Anti-bot tracking
mapping(address => bool) public isBot;
bool public antiBotEnabled = true;
uint256 public tradingEnabledTime;
uint256 public botProtectionDuration = 300; // 5 minutes in seconds
// Vesting structure
struct VestingSchedule {
uint256 totalAmount;
uint256 released;
uint256 startTime;
uint256 duration;
}
mapping(address => VestingSchedule) public vestingSchedules;
uint256 public vestingStartTime = 1748736000; // June 1, 2026 00:00:00 UTC
uint256 public vestingDuration = 18 * 30 days; // 18 months (approximately)
event BotDetected(address indexed bot);
event BotStatusUpdated(address indexed account, bool isBot);
event VestingScheduleCreated(address indexed beneficiary, uint256 amount);
event TokensReleased(address indexed beneficiary, uint256 amount);
event TaxUpdated(uint256 buyTax, uint256 sellTax, uint256 botTax);
event BurnUpdated(uint256 buyBurn, uint256 sellBurn);
event LiquidityWalletUpdated(address indexed newWallet);
event VestingConfigUpdated(uint256 startTime, uint256 duration);
event TradingEnabled(uint256 timestamp);
constructor() ERC20("UbuntuCoin", "UBU") Ownable() {
// Set up Uniswap router based on chain
if (block.chainid == 1) {
// Ethereum Mainnet
uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
} else if (block.chainid == 11155111) {
// Sepolia
uniswapV2Router = IUniswapV2Router02(0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3);
}
// Create Uniswap pair
uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory())
.createPair(address(this), uniswapV2Router.WETH());
// Mint total supply
_mint(msg.sender, 10_000_000_000 * 10 ** decimals());
// Exempt owner, contract, and dead address from tax
isExcludedFromFees[msg.sender] = true;
isExcludedFromFees[address(this)] = true;
isExcludedFromFees[address(0xdead)] = true;
isExcludedFromFees[liquidityWallet] = true;
// Trading will be enabled by owner
tradingEnabledTime = 0;
}
function decimals() public view virtual override returns (uint8) {
return 6;
}
/**
* @dev Override transfer to apply tax ONLY on DEX trades with anti-bot logic
* Regular wallet-to-wallet transfers have NO tax
*/
function _transfer(address from, address to, uint256 amount) internal virtual override {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
if (amount == 0) {
super._transfer(from, to, 0);
return;
}
// Check if trading is enabled (allow owner and excluded addresses to trade before launch)
if (tradingEnabledTime == 0 && !isExcludedFromFees[from] && !isExcludedFromFees[to]) {
require(from != uniswapV2Pair && to != uniswapV2Pair, "Trading not enabled yet");
}
// Anti-bot detection: Mark as bot if buying in first blocks after launch
if (antiBotEnabled && tradingEnabledTime > 0 &&
block.timestamp <= tradingEnabledTime + botProtectionDuration &&
from == uniswapV2Pair && !isExcludedFromFees[to] && to != address(uniswapV2Router)) {
isBot[to] = true;
emit BotDetected(to);
}
uint256 senderBalance = _balances[from];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
// Calculate fees (only on buys/sells, NOT on wallet transfers)
uint256 fees = 0;
uint256 burnAmount = 0;
if (!isExcludedFromFees[from] && !isExcludedFromFees[to]) {
// Apply 99% tax to bots selling
if (isBot[from] && to == uniswapV2Pair) {
fees = (amount * botTax) / TAX_DENOMINATOR;
}
// On sell (transfer to Uniswap pair)
else if (to == uniswapV2Pair && sellTax > 0) {
fees = (amount * sellTax) / TAX_DENOMINATOR;
burnAmount = (amount * sellBurn) / TAX_DENOMINATOR;
}
// On buy (transfer from Uniswap pair)
else if (from == uniswapV2Pair && buyTax > 0) {
fees = (amount * buyTax) / TAX_DENOMINATOR;
burnAmount = (amount * buyBurn) / TAX_DENOMINATOR;
}
}
// Execute transfer
unchecked {
_balances[from] = senderBalance - amount;
}
if (fees > 0) {
// Transfer fees to liquidity wallet
_balances[liquidityWallet] += fees;
emit Transfer(from, liquidityWallet, fees);
}
if (burnAmount > 0) {
// Burn tokens (send to dead address)
_balances[address(0xdead)] += burnAmount;
emit Transfer(from, address(0xdead), burnAmount);
}
amount -= (fees + burnAmount);
_balances[to] += amount;
emit Transfer(from, to, amount);
}
// ============================================
// VESTING FUNCTIONS
// ============================================
/**
* @dev Create a vesting schedule for a beneficiary (only owner)
* @param beneficiary Address to receive vested tokens
* @param amount Total amount of tokens to vest
*/
function createVestingSchedule(address beneficiary, uint256 amount) external onlyOwner {
require(beneficiary != address(0), "Beneficiary is zero address");
require(amount > 0, "Amount must be greater than 0");
require(vestingSchedules[beneficiary].totalAmount == 0, "Vesting schedule already exists");
vestingSchedules[beneficiary] = VestingSchedule({
totalAmount: amount,
released: 0,
startTime: vestingStartTime,
duration: vestingDuration
});
// Transfer tokens to contract for vesting
_transfer(msg.sender, address(this), amount);
emit VestingScheduleCreated(beneficiary, amount);
}
/**
* @dev Calculate releasable tokens for a beneficiary
* @param beneficiary Address to check
*/
function releasableAmount(address beneficiary) public view returns (uint256) {
VestingSchedule memory schedule = vestingSchedules[beneficiary];
if (schedule.totalAmount == 0) {
return 0;
}
if (block.timestamp < schedule.startTime) {
return 0;
}
if (block.timestamp >= schedule.startTime + schedule.duration) {
return schedule.totalAmount - schedule.released;
}
uint256 timeFromStart = block.timestamp - schedule.startTime;
uint256 vestedAmount = (schedule.totalAmount * timeFromStart) / schedule.duration;
return vestedAmount - schedule.released;
}
/**
* @dev Release vested tokens to beneficiary
*/
function releaseVestedTokens() external {
uint256 unreleased = releasableAmount(msg.sender);
require(unreleased > 0, "No tokens to release");
vestingSchedules[msg.sender].released += unreleased;
_balances[address(this)] -= unreleased;
_balances[msg.sender] += unreleased;
emit TokensReleased(msg.sender, unreleased);
emit Transfer(address(this), msg.sender, unreleased);
}
/**
* @dev Get vesting schedule information
*/
function getVestingSchedule(address beneficiary) external view returns (
uint256 totalAmount,
uint256 released,
uint256 releasable,
uint256 startTime,
uint256 duration
) {
VestingSchedule memory schedule = vestingSchedules[beneficiary];
return (
schedule.totalAmount,
schedule.released,
releasableAmount(beneficiary),
schedule.startTime,
schedule.duration
);
}
// ============================================
// ANTI-BOT FUNCTIONS
// ============================================
/**
* @dev Enable trading (can only be called once by owner)
*/
function enableTrading() external onlyOwner {
require(tradingEnabledTime == 0, "Trading already enabled");
tradingEnabledTime = block.timestamp;
emit TradingEnabled(block.timestamp);
}
/**
* @dev Manually mark addresses as bots
*/
function setBotStatus(address[] calldata accounts, bool status) external onlyOwner {
for (uint256 i = 0; i < accounts.length; i++) {
isBot[accounts[i]] = status;
emit BotStatusUpdated(accounts[i], status);
}
}
/**
* @dev Toggle anti-bot mechanism
*/
function setAntiBotEnabled(bool enabled) external onlyOwner {
antiBotEnabled = enabled;
}
/**
* @dev Update bot protection duration
*/
function setBotProtectionDuration(uint256 duration) external onlyOwner {
botProtectionDuration = duration;
}
// ============================================
// ADMIN FUNCTIONS
// ============================================
/**
* @dev Update tax rates
*/
function updateTax(uint256 _buyTax, uint256 _sellTax, uint256 _botTax) external onlyOwner {
require(_buyTax <= 10000, "Buy tax too high"); // Max 10%
require(_sellTax <= 10000, "Sell tax too high"); // Max 10%
require(_botTax <= 10000, "Bot tax too high"); // Max 10%
buyTax = _buyTax;
sellTax = _sellTax;
botTax = _botTax;
emit TaxUpdated(_buyTax, _sellTax, _botTax);
}
/**
* @dev Update burn rates
*/
function updateBurn(uint256 _buyBurn, uint256 _sellBurn) external onlyOwner {
require(_buyBurn <= 10000, "Buy burn too high"); // Max 1%
require(_sellBurn <= 10000, "Sell burn too high"); // Max 1%
buyBurn = _buyBurn;
sellBurn = _sellBurn;
emit BurnUpdated(_buyBurn, _sellBurn);
}
/**
* @dev Update liquidity wallet address
*/
function updateLiquidityWallet(address newWallet) external onlyOwner {
require(newWallet != address(0), "Invalid wallet address");
liquidityWallet = newWallet;
isExcludedFromFees[newWallet] = true;
emit LiquidityWalletUpdated(newWallet);
}
/**
* @dev Update vesting configuration
*/
function updateVestingConfig(uint256 _startTime, uint256 _duration) external onlyOwner {
require(_startTime > block.timestamp, "Start time must be in future");
require(_duration > 0, "Duration must be greater than 0");
vestingStartTime = _startTime;
vestingDuration = _duration;
emit VestingConfigUpdated(_startTime, _duration);
}
/**
* @dev Set fee exclusion status
*/
function setExcludedFromFees(address account, bool excluded) external onlyOwner {
isExcludedFromFees[account] = excluded;
}
}