Contract Source Code:
File 1 of 1 : Test3
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/* ────────────────────────────────────────────────────────────── */
/* CONTEXT & OWNABLE */
/* ────────────────────────────────────────────────────────────── */
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
_owner = _msgSender();
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_msgSender() == _owner, "Ownable: caller is not the owner");
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "Ownable: new owner is zero");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
}
/* ────────────────────────────────────────────────────────────── */
/* ERC20 INTERFACES & IMPLEMENTATION */
/* ────────────────────────────────────────────────────────────── */
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);
}
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 internal _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view override returns (string memory) { return _name; }
function symbol() public view override returns (string memory) { return _symbol; }
function decimals() public pure override returns (uint8) { return 18; }
function totalSupply() public view override returns (uint256) { return _totalSupply; }
function balanceOf(address account) public view override returns (uint256) { return _balances[account]; }
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer exceeds allowance");
unchecked { _approve(sender, _msgSender(), currentAllowance - amount); }
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); }
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0) && recipient != address(0), "ERC20: zero address");
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: insufficient 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");
_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) && spender != address(0), "ERC20: zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
/* ────────────────────────────────────────────────────────────── */
/* SAFE MATH LIBRARIES */
/* ────────────────────────────────────────────────────────────── */
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if(a == 0) return 0;
uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library SafeMathInt {
int256 private constant MIN_INT256 = int256(1) << 255;
int256 private constant MAX_INT256 = ~(int256(1) << 255);
function mul(int256 a, int256 b) internal pure returns (int256) {
int256 c = a * b;
require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256), "SafeMathInt: multiplication overflow");
require(b == 0 || c / b == a, "SafeMathInt: multiplication overflow");
return c;
}
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != -1 || a != MIN_INT256, "SafeMathInt: division overflow");
return a / b;
}
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a), "SafeMathInt: subtraction overflow");
return c;
}
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a), "SafeMathInt: addition overflow");
return c;
}
function abs(int256 a) internal pure returns (int256) {
require(a != MIN_INT256, "SafeMathInt: abs overflow");
return a < 0 ? -a : a;
}
function toUint256Safe(int256 a) internal pure returns (uint256) {
require(a >= 0, "SafeMathInt: negative to uint");
return uint256(a);
}
}
library SafeMathUint {
function toInt256Safe(uint256 a) internal pure returns (int256) {
int256 b = int256(a); require(b >= 0, "SafeMathUint: overflow");
return b;
}
}
/* ────────────────────────────────────────────────────────────── */
/* Uniswap V2 FACTORY & ROUTER INTERFACES (SONIC) */
/* ────────────────────────────────────────────────────────────── */
/*
NOTE: The key fix is using WETH() instead of WSONIC().
*/
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); // <--- Use WETH instead of WSONIC
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 tokenAmount,
uint256 minETH,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 tokenAmount,
uint256 minTokens,
address[] calldata path,
address to,
uint256 deadline
) external;
}
/* ────────────────────────────────────────────────────────────── */
/* DIVIDEND TRACKER CONTRACT */
/* ────────────────────────────────────────────────────────────── */
contract DividendTracker is Ownable {
using SafeMathInt for int256;
using SafeMath for uint256;
uint256 constant internal magnitude = 2**128;
address public rewardToken;
uint256 public magnifiedDividendPerShare;
mapping(address => uint256) public holderBalance;
uint256 public totalBalance;
mapping(address => int256) public magnifiedDividendCorrections;
mapping(address => uint256) public withdrawnDividends;
event DividendsDistributed(address indexed from, uint256 amount);
event DividendClaimed(address indexed account, uint256 amount);
constructor(address _rewardToken) {
rewardToken = _rewardToken;
}
function distributeDividends(uint256 amount) external onlyOwner {
require(totalBalance > 0, "DividendTracker: no holders");
magnifiedDividendPerShare = magnifiedDividendPerShare.add( amount.mul(magnitude).div(totalBalance) );
emit DividendsDistributed(msg.sender, amount);
}
function setBalance(address account, uint256 newBalance) external onlyOwner {
uint256 current = holderBalance[account];
holderBalance[account] = newBalance;
if(newBalance > current) {
uint256 inc = newBalance.sub(current);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account].sub(
int256(magnifiedDividendPerShare.mul(inc))
);
totalBalance = totalBalance.add(inc);
} else if(newBalance < current) {
uint256 dec = current.sub(newBalance);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account].add(
int256(magnifiedDividendPerShare.mul(dec))
);
totalBalance = totalBalance.sub(dec);
}
}
function withdrawableDividendOf(address account) public view returns (uint256) {
int256 accumulative = int256(holderBalance[account].mul(magnifiedDividendPerShare))
+ magnifiedDividendCorrections[account];
if(accumulative < 0) return 0;
uint256 totalAccumulated = uint256(accumulative) / magnitude;
if(totalAccumulated <= withdrawnDividends[account]) return 0;
return totalAccumulated.sub(withdrawnDividends[account]);
}
function processAccount(address account) external onlyOwner returns (uint256) {
uint256 amount = withdrawableDividendOf(account);
if(amount > 0) {
withdrawnDividends[account] = withdrawnDividends[account].add(amount);
IERC20(rewardToken).transfer(account, amount);
emit DividendClaimed(account, amount);
}
return amount;
}
}
/* ────────────────────────────────────────────────────────────── */
/* MAIN TOKEN CONTRACT: TEST3 */
/* ────────────────────────────────────────────────────────────── */
contract Test3 is ERC20, Ownable {
using SafeMath for uint256;
IUniswapV2Router02 public UniswapV2Router;
address public UniswapV2Pair;
// Tax wallet for marketing funds.
address public taxWallet;
// Reward token (wSONIC) for dividends.
address public rewardToken;
// Dividend tracker instance.
DividendTracker public dividendTracker;
// Limits and thresholds.
uint256 public maxWallet;
uint256 public swapTokensAtAmount;
bool public limitsInEffect = true;
bool private swapping;
// Fee structure (in basis points out of 1000):
uint256 public rewardsFeeBuy = 30; // 3%
uint256 public taxFeeBuy = 20; // 2%
uint256 public totalBuyFees = 50; // 5%
uint256 public rewardsFeeSell = 30; // 3%
uint256 public taxFeeSell = 20; // 2%
uint256 public totalSellFees = 50; // 5%
// Accumulated fee counters.
uint256 public tokensForRewards;
uint256 public tokensForTax;
// Mapping to track fee exclusion.
mapping(address => bool) private _isExcludedFromFees;
constructor() ERC20("Test4", "TEST4") {
uint256 totalSupply = 1 * 1e6 * 1e18; // 1,000,000 supply, example
_mint(msg.sender, totalSupply);
// Set max wallet to 2% of supply.
maxWallet = totalSupply.mul(2).div(100);
// Set swap threshold to 0.2% of supply.
swapTokensAtAmount = totalSupply.mul(2).div(1000);
// Set initial tax wallet to deployer.
taxWallet = msg.sender;
// Hardcode the reward token to wSONIC (the actual address).
rewardToken = 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38;
// Initialize dividend tracker.
dividendTracker = new DividendTracker(rewardToken);
// Initialize router & pair - using WETH() instead of WSONIC().
UniswapV2Router = IUniswapV2Router02(0x95a7e403d7cF20F675fF9273D66e94d35ba49fA3);
UniswapV2Pair = IUniswapV2Factory(UniswapV2Router.factory())
.createPair(address(this), UniswapV2Router.WETH());
// Exclude owner and contract from fees.
_isExcludedFromFees[owner()] = true;
_isExcludedFromFees[address(this)] = true;
}
/* ───────────────────────── ADMIN FUNCTIONS ───────────────────────── */
function claim() external {
dividendTracker.processAccount(msg.sender);
}
function removeLimits() external onlyOwner {
limitsInEffect = false;
}
function updateBuyFees(uint256 _newRewardsFeeBuy, uint256 _newTaxFeeBuy) external onlyOwner {
rewardsFeeBuy = _newRewardsFeeBuy;
taxFeeBuy = _newTaxFeeBuy;
totalBuyFees = _newRewardsFeeBuy + _newTaxFeeBuy;
require(totalBuyFees <= 100, "Buy fees too high");
}
function updateSellFees(uint256 _newRewardsFeeSell, uint256 _newTaxFeeSell) external onlyOwner {
rewardsFeeSell = _newRewardsFeeSell;
taxFeeSell = _newTaxFeeSell;
totalSellFees = _newRewardsFeeSell + _newTaxFeeSell;
require(totalSellFees <= 100, "Sell fees too high");
}
function updateMaxWalletAmount(uint256 newMaxWallet) external onlyOwner {
maxWallet = newMaxWallet;
}
function updateTaxWallet(address newTaxWallet) external onlyOwner {
require(newTaxWallet != address(0), "Zero address");
taxWallet = newTaxWallet;
}
function updateRewardToken(address newRewardToken) external onlyOwner {
require(newRewardToken != address(0), "Zero address");
rewardToken = newRewardToken;
dividendTracker = new DividendTracker(newRewardToken);
}
function updateRouter(address newRouter) external onlyOwner {
require(newRouter != address(0), "Zero address");
UniswapV2Router = IUniswapV2Router02(newRouter);
UniswapV2Pair = IUniswapV2Factory(UniswapV2Router.factory())
.createPair(address(this), UniswapV2Router.WETH());
}
function excludeFromFees(address account, bool excluded) external onlyOwner {
_isExcludedFromFees[account] = excluded;
}
function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) external onlyOwner {
for (uint256 i = 0; i < accounts.length; i++) {
_isExcludedFromFees[accounts[i]] = excluded;
}
}
/* ───────────────────── CORE TRANSFER & FEE LOGIC ───────────────────── */
// Trading is always enabled.
function _transfer(address from, address to, uint256 amount) internal override {
// Enforce max wallet if limits are active (except for pair and owner).
if(limitsInEffect && to != UniswapV2Pair && to != owner()) {
require(balanceOf(to).add(amount) <= maxWallet, "Exceeds max wallet");
}
uint256 fees = 0;
if(!swapping && !_isExcludedFromFees[from] && !_isExcludedFromFees[to] && from != owner() && to != owner()){
if(from == UniswapV2Pair) { // Buy
fees = amount.mul(totalBuyFees).div(1000);
tokensForRewards = tokensForRewards.add(fees.mul(rewardsFeeBuy).div(totalBuyFees));
tokensForTax = tokensForTax.add(fees.mul(taxFeeBuy).div(totalBuyFees));
} else if(to == UniswapV2Pair) { // Sell
fees = amount.mul(totalSellFees).div(1000);
tokensForRewards = tokensForRewards.add(fees.mul(rewardsFeeSell).div(totalSellFees));
tokensForTax = tokensForTax.add(fees.mul(taxFeeSell).div(totalSellFees));
}
}
if(fees > 0) {
super._transfer(from, address(this), fees);
amount = amount.sub(fees);
}
super._transfer(from, to, amount);
// Update dividend tracker balances.
dividendTracker.setBalance(from, balanceOf(from));
dividendTracker.setBalance(to, balanceOf(to));
// Auto-process dividends for both sender and recipient.
if(!swapping) {
swapping = true;
dividendTracker.processAccount(from);
dividendTracker.processAccount(to);
swapping = false;
}
// If the contract's token balance exceeds the swap threshold and the transfer is not a buy, trigger swapBack.
if(!swapping && balanceOf(address(this)) >= swapTokensAtAmount && from != UniswapV2Pair) {
swapBack();
}
}
/* ───────────────────── SWAP & DIVIDEND PROCESSING ───────────────────── */
function swapBack() private {
swapping = true;
uint256 contractBalance = balanceOf(address(this));
uint256 totalTokensToSwap = tokensForRewards.add(tokensForTax);
if(contractBalance == 0 || totalTokensToSwap == 0) { swapping = false; return; }
uint256 taxPortion = tokensForTax;
uint256 rewardsPortion = tokensForRewards;
tokensForTax = 0;
tokensForRewards = 0;
// Swap tax portion for ETH and send to tax wallet.
swapTokensForEth(taxPortion);
(bool sent, ) = taxWallet.call{value: address(this).balance}("");
require(sent, "ETH transfer failed");
// Swap rewards portion for the reward token and distribute dividends.
uint256 initialRewardBal = IERC20(rewardToken).balanceOf(address(this));
swapTokensForReward(rewardsPortion);
uint256 newRewardBal = IERC20(rewardToken).balanceOf(address(this)).sub(initialRewardBal);
if(newRewardBal > 0) {
dividendTracker.distributeDividends(newRewardBal);
}
swapping = false;
}
function swapTokensForEth(uint256 tokenAmount) private {
address[] memory path = new address[](2);
path[0] = address(this);
// Use WETH() instead of WSONIC()
path[1] = UniswapV2Router.WETH();
_approve(address(this), address(UniswapV2Router), tokenAmount);
UniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
}
function swapTokensForReward(uint256 tokenAmount) private {
address[] memory path = new address[](3);
path[0] = address(this);
// Use WETH() instead of WSONIC()
path[1] = UniswapV2Router.WETH();
path[2] = rewardToken;
_approve(address(this), address(UniswapV2Router), tokenAmount);
UniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
}
// Allow the contract to receive ETH from swaps.
receive() external payable {}
}