Address
0x6dcfb4ed7b9aa0bf032e9c8f37ed066bd52cf27cCurrent Holdings
$0.00
TXs sent
not counted
First Active
2026-05-22
block 26,597,715
Last Active
30 days ago
block 27,309,744
Net worth historyi
7 snapshots · to block 27,522,600coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchPlsxSmartTokensolc 0.8.35+commit.47b9deddruntime exact · creation not verified
// SPDX-License-Identifier: MIT
//
// Plsx Forge — tax-token launcher (fork of Icaria Forge for plsx.fun)
// Web: https://plsx.fun
//
pragma solidity ^0.8.20;
import { PlsxSmartToken } from "./PlsxSmartToken.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IPlsxHelpers } from "./interfaces/IPlsxHelpers.sol";
// --- Custom errors for gas & bytecode savings ---
error Denied();
error InsufficientPayment();
error NotFactoryToken();
error FeeTooHigh();
error InvalidAddress();
error WalletExists();
error WalletsEmpty();
error InvalidAmount();
error InvalidInput();
error LowAmount();
error TransferFailed();
contract PlsxSmartTokenFactory is Ownable, ReentrancyGuard {
uint256 public constant GLOBAL_DIVIDER = 10000;
// plsx.fun platform fee taken from each token's total taxes.
// 45 / 10000 = 0.45% (matches Icaria). E.g. if a token's total tax is 1%,
// the platform slice is 0.0045%. Adjust with setPlsxfunFee.
uint256 public PLSXFUN_FEE = 45;
// Single wallet that receives ALL platform fees — hardcoded so a deploy
// can never misroute them: the PLS creation fee (distributionWallets), the
// token tax slice (PLSXFUN_WALLET), and any processPLS sweeps
// (processorWallet) all default to this address in the constructor.
address public constant FEE_WALLET = 0x5Cd66b653c3973B3A82453eba5D07F56F5c1e8ac;
// Wallet that receives the platform's tax slice (was ICARIA_WALLET in the
// upstream Icaria Forge). The created token reads this via the factory so
// its non-accumulated platform fee is routed here. Defaults to FEE_WALLET.
address public PLSXFUN_WALLET;
address public manager;
uint256 public tokenCreationPrice;
address public helpersAddress;
mapping(address => bool) public isFactoryToken;
// Wallets that split the PLS creation fee paid per taxed token.
address processorWallet;
address[] public distributionWallets;
event TokenCreated(address indexed tokenAddress, string name, string symbol, address indexed owner);
modifier onlyManager() {
if(!(owner() == _msgSender() || manager == _msgSender() || processorWallet == _msgSender())) revert Denied();
_;
}
// No distribution-wallets param — ALL fee sinks are locked to FEE_WALLET
// on deploy so fees can't be misrouted. The owner can still rebalance
// later via setProcessorWallet / setPlsxfunWallet / add/removeDistributionWallet.
constructor(uint256 _tokenCreationPrice, address _helpersAddress) Ownable(msg.sender) {
tokenCreationPrice = _tokenCreationPrice;
helpersAddress = _helpersAddress;
PLSXFUN_WALLET = FEE_WALLET; // platform tax slice
processorWallet = FEE_WALLET; // processPLS sweeps
distributionWallets.push(FEE_WALLET); // PLS creation fee
}
// NOTE: ownership-renounce and trading-enabled are NOT caller options on
// the plsx.fun fork — they're enforced unconditionally below. Every token
// forged here ships ownerless (deployer can't change taxes / mint / rug)
// and with trading already live. The upstream `ownershipRenounced` and
// `_tradingEnabled` params were removed so there's no way to pass `false`.
function createToken(
string memory name_,
string memory symbol_,
uint256 _initialSupply,
IPlsxHelpers.Tax[] memory _taxes,
address _plsxSmartTrader
) external payable nonReentrant returns (address) {
if (_taxes.length > 0) {
if(msg.value < tokenCreationPrice) revert InsufficientPayment();
}
PlsxSmartToken newToken = new PlsxSmartToken(
name_,
symbol_,
address(this),
msg.sender,
_initialSupply,
_taxes,
_plsxSmartTrader,
address(this),
helpersAddress,
true // _tradingEnabled — always on, not caller-selectable
);
isFactoryToken[address(newToken)] = true;
// Always renounce — not caller-selectable.
newToken.renounceOwnership();
if (_taxes.length > 0 && tokenCreationPrice > 0) {
_withdrawPLS(tokenCreationPrice);
}
emit TokenCreated(address(newToken), name_, symbol_, msg.sender);
return address(newToken);
}
function getTokenTaxData(address tokenAddress) external view returns (IPlsxHelpers.Tax[] memory) {
if(!isFactoryToken[tokenAddress]) revert NotFactoryToken();
return PlsxSmartToken(payable(tokenAddress)).getTaxes();
}
function getTokenData(address tokenAddress) external view returns (
string memory name,
string memory symbol,
uint256 initialSupply,
uint256 currentSupply,
bool ownershipRenounced,
IPlsxHelpers.Tax[] memory taxes,
bool tradingEnabled
) {
if(!isFactoryToken[tokenAddress]) revert NotFactoryToken();
PlsxSmartToken token = PlsxSmartToken(payable(tokenAddress));
name = token.name();
symbol = token.symbol();
initialSupply = token.initialSupply();
currentSupply = token.totalSupply();
ownershipRenounced = token.owner() == address(0);
taxes = token.getTaxes();
tradingEnabled = token.tradingEnabled();
return (name, symbol, initialSupply, currentSupply, ownershipRenounced, taxes, tradingEnabled);
}
function setTokenCreationPrice(uint256 newPrice) external onlyOwner {
tokenCreationPrice = newPrice;
}
function setPlsxfunFee(uint256 newFee) external onlyOwner {
if(newFee > GLOBAL_DIVIDER) revert FeeTooHigh();
PLSXFUN_FEE = newFee;
}
function setPlsxfunWallet(address wallet) external onlyOwner {
if(wallet == address(0)) revert InvalidAddress();
PLSXFUN_WALLET = wallet;
}
function setProcessorWallet(address wallet) external onlyOwner {
if(wallet == address(0)) revert InvalidAddress();
processorWallet = wallet;
}
function addDistributionWallet(address wallet) external onlyOwner {
if(wallet == address(0)) revert InvalidAddress();
for(uint256 i = 0; i < distributionWallets.length; i++) {
if(distributionWallets[i] == wallet) {
revert WalletExists();
}
}
distributionWallets.push(wallet);
}
function removeDistributionWallet(address walletToRemove) external onlyOwner {
if(distributionWallets.length == 0) revert WalletsEmpty();
for(uint256 i = 0; i < distributionWallets.length; i++) {
if(distributionWallets[i] == walletToRemove) {
if (i != distributionWallets.length - 1) {
distributionWallets[i] = distributionWallets[distributionWallets.length - 1];
}
distributionWallets.pop();
return;
}
}
revert();
}
function getDistributionWallets() external view returns (address[] memory) {
return distributionWallets;
}
function processPLS(uint256 amount) external onlyManager {
if(amount == 0 || amount > address(this).balance) revert InvalidAmount();
(bool success, ) = processorWallet.call{value: amount}("");
}
function _withdrawPLS(uint256 amount) internal {
uint256 walletsCount = distributionWallets.length;
if(!(walletsCount > 0 && amount > 0 && amount <= address(this).balance)) revert InvalidInput();
uint256 amountPerWallet = amount / walletsCount;
if(amountPerWallet == 0) revert LowAmount();
for(uint256 i = 0; i < walletsCount; i++) {
(bool success, ) = distributionWallets[i].call{value: amountPerWallet}("");
}
}
function withdrawPLS(uint256 amount) external onlyManager nonReentrant {
_withdrawPLS(amount);
}
function setManager(address newManager) external onlyOwner {
manager = newManager;
}
function withdrawERC20(address tokenAddress, address to) external onlyManager nonReentrant {
if(tokenAddress == address(0)) revert InvalidAddress();
IERC20 token = IERC20(tokenAddress);
uint256 balance = token.balanceOf(address(this));
if(!token.transfer(to, balance)) revert TransferFailed();
}
receive() external payable {}
}