Contract Diff Checker

Contract Name:
Incubator

Contract Source Code:

/*

 █▀ █▀█ █▄░█ █ █▀▀ █▀▀ ▄▀█ █▀▀ ▀█▀ █▀█ █▀█ █▄█
 ▄█ █▄█ █░▀█ █ █▄▄ █▀░ █▀█ █▄▄ ░█░ █▄█ █▀▄ ░█░

  Trade on SonicFactory and have fun!
  Web:      https://sonicfactory.fun/

*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

import "./interfaces/IERC20.sol";
import "./interfaces/IIncubatorToken.sol";
import "./interfaces/IIncubatorPair.sol";
import "./interfaces/IUniswapV2Router.sol";
import "./interfaces/IUniswapV2Factory.sol";
import "./Ownable.sol";
import "./Token/Token.sol";

contract Incubator is Ownable {
  uint8 private _PAUSED;
  uint8 private _initialized;
  uint8 private constant _DECIMALS = 18;
  uint24 private _SWAP_FEE;
  uint24 private _REFERRAL_FEE;
  uint24 private _ESCAPE_FEE;
  uint24 private _ESCAPE_CREATOR_FEE;
  uint24 private _TOKEN_INITIAL_PERCENT;
  uint112 private _ETH_RESERVE_VIRTUAL_INITIAL;
  uint112 private _ETH_RESERVE_ESCAPE_TARGET;
  uint256 private _CREATION_FEE;
  uint256 private constant _TOTAL_SUPPLY = 1_000_000_000 ether;

  address private _AUTHORIZED;
  address private _TREASURY;
  address private _ROUTER_INCUBATOR;
  address private _WETH_INCUBATOR;
  address[] private _tokenList;
  address[] private _unauthorizedList;

  mapping(address => TokenData) private _tokenData;
  mapping(address => RouterData) private _routerData;
  mapping(address => bool) private _creatorData;
  mapping(address => address) private _pairData;

  struct TokenData {
    bytes32 salt;
    uint24 maxBalance;
    uint24 fee;
    uint24 tax;
    uint24 ref;
    uint32 creation;
    uint32 launch;
    uint32 escaped;
    uint112 ethReserveEscapeTarget;
    uint112 ethReserveVirtualInitial;
    uint112 ethReserveEscaped;
    uint112 tokenReserveInitial;
    uint256 tokenReserveEscaped;
    uint256 initialSupply;
    uint256 creationFee;
    uint256 escapeFee;
    address creator;
    address referral;
    address routerIncubator;
    address pairIncubator;
    address routerFinal;
    bool autoEscape;
  }

  struct TokenDataView {
    string name;
    string symbol;
    uint8 decimals;
    uint24 maxBalance;
    uint24 fee;
    uint24 tax;
    uint24 ref;
    uint24 holders;
    uint32 creation;
    uint32 launch;
    uint32 escaped;
    uint112 ethReserveEscapeTarget;
    uint112 ethReserveEscaped;
    uint112 ethReserveVirtualInitial;
    uint112 ethReserve;
    uint112 tokenReserveInitial;
    uint112 tokenReserve;
    uint256 tokenReserveEscaped;
    uint256 initialSupply;
    uint256 totalSupply;
    uint256 creationFee;
    uint256 escapeFee;
    address creator;
    address referral;
    address routerIncubator;
    address pairIncubator;
    address routerFinal;
    bool autoEscape;
  }

  struct RouterData {
    bool exists;
    bool enabled;
  }

  struct TokenListView {
    address token;
    address creator;
    bytes32 salt;
  }

  struct currentStatusView {
    address routerIncubator;
    uint8 paused;
    uint8 decimals;
    uint24 swapFee;
    uint24 referralFee;
    uint24 escapeFee;
    uint24 escapeCreatorFee;
    uint24 tokenInitialPercent;
    uint112 ethReserveVirtualInitial;
    uint112 ethReserveEscapeTarget;
    uint256 creationFee;
    uint256 totalSupply;
  }

  event TokenDeployed(address indexed token, address indexed creator, bytes32 salt);
  event TokenEscaped(address indexed token, uint32 escapeTime, uint112 ethReserveEscaped, uint256 tokenReserveEscaped, uint256 escapeFee);
  event TokenTraded(address indexed token, uint32 tradeTime, address indexed user, bool buy, uint112 ethReserve, uint112 tokenReserve, uint256 ethAmount, uint256 tokenAmount, uint256 feeAmount, uint256 taxAmount, uint256 refAmount);
  event WithdrawnETH(address indexed to, uint256 value);
  event WithdrawnERC20(address token, address indexed to, uint256 value);

  error ErrorPaused();
  error ErrorReferral();
  error ErrorTransfer(address to, uint256 value);
  error ErrorRouterUnavailable(address router);
  error ErrorTokenMinimumValue(uint256 value);
  error ErrorUnknownToken(address token);
  error ErrorUnescapedToken(address token);
  error ErrorTokenMaxBalance(uint24 percent);
  error ErrorTokenTax(uint24 percent);
  error ErrorTokenLiquidity(uint256 tokenAmount, uint256 ethAmount);
  error ErrorInvalidRange();

  modifier onlyOwnerOrAuthorized() {
    if (msg.sender != _owner && msg.sender != _AUTHORIZED) { revert ErrorUnauthorized(msg.sender); }

    _;
  }

  modifier isToken(address token) {
    if (_tokenData[token].creator == address(0)) { revert ErrorUnknownToken(token); }

    _;
  }

  modifier isPairOfToken() {
    if (_pairData[msg.sender] == address(0)) { revert ErrorUnauthorized(msg.sender); }

    _;
  }

  constructor() payable {}

  function initialize() external {
    require(_initialized == 0);

    _SWAP_FEE = 1_000;               // 1%
    _REFERRAL_FEE = 20_000;          // 20% of _SWAP_FEE
    _ESCAPE_FEE = 5_000;             // 5%
    _ESCAPE_CREATOR_FEE = 50_000;    // 50% of _ESCAPE_FEE
    _TOKEN_INITIAL_PERCENT = 100_000; // 100%
    _ETH_RESERVE_VIRTUAL_INITIAL = 0.8 ether;
    _ETH_RESERVE_ESCAPE_TARGET = 3.8 ether;

    _transferOwnership(msg.sender);
    _initialized = 1;
  }

  function setPaused(bool status) external onlyOwner {
    _PAUSED = status ? 1 : 0;
  }

  function setAuthorized(address authorized) external onlyOwner {
    _AUTHORIZED = authorized;
  }

  function setFees(uint256 creationFee, uint24 swapFee, uint24 referralFee, uint24 escapeFee, uint24 escapeCreatorFee) external onlyOwner {
    require(swapFee <= 5_000);            // Max. 5%
    require(referralFee <= 50_000);       // Max. 50% of swapFee
    require(escapeFee <= 25_000);         // Max. 25%
    require(escapeCreatorFee <= 100_000); // Max. 100% of escapeFee

    _CREATION_FEE = creationFee;
    _SWAP_FEE = swapFee;
    _REFERRAL_FEE = referralFee;
    _ESCAPE_FEE = escapeFee;
    _ESCAPE_CREATOR_FEE = escapeCreatorFee;
  }

  function setTokenReserves(uint24 percent) external onlyOwner {
    require(percent >= 50_000 && percent <= 100_000); // 50% to 100%

    _TOKEN_INITIAL_PERCENT = percent;
  }

  function setEthReserves(uint112 ethReserveVirtualInitial, uint112 ethReserveEscapeTarget) external onlyOwner {
    _ETH_RESERVE_VIRTUAL_INITIAL = ethReserveVirtualInitial;
    _ETH_RESERVE_ESCAPE_TARGET = ethReserveEscapeTarget;
  }

  function setRouterIncubator(address router) external onlyOwner {
    _ROUTER_INCUBATOR = router;
    _WETH_INCUBATOR = IUniswapV2Router(router).WETH();
  }

  function setRouterFinal(address router, bool enabled, address[] calldata related) external onlyOwner {
    RouterData storage _router = _routerData[router];

    _router.enabled = enabled;

    if (!_router.exists) {
      _router.exists = true;

      _unauthorizedList.push(router);

      unchecked {
        uint256 cnt = related.length;

        for (uint256 i; i < cnt; i++) { _unauthorizedList.push(related[i]); }
      }
    }
  }

  function listTokens(uint256 offset, uint256 limit) external view returns (TokenListView[] memory) {
    uint256 cnt = _tokenList.length;
    uint256 total;

    unchecked {
      total = (offset + limit > cnt) ? (cnt - offset) : limit;

      if (total > cnt) { revert ErrorInvalidRange(); }
    }

    TokenListView[] memory data = new TokenListView[](total);

    unchecked {
      uint256 j;
      uint256 max = offset + total;

      for (uint256 i = offset; i < max; i++) {
        address token = _tokenList[i];

        TokenData storage tokenData = _tokenData[token];

        data[j++] = TokenListView(token, tokenData.creator, tokenData.salt);
      }
    }

    return data;
  }

  function getTokenData(address token) public view isToken(token) returns (TokenDataView memory data) {
    TokenData storage tokenData = _tokenData[token];

    data.name = IERC20(token).name();
    data.symbol = IERC20(token).symbol();
    data.decimals = IERC20(token).decimals();
    data.creator = tokenData.creator;
    data.referral = tokenData.referral;
    data.creation = tokenData.creation;
    data.launch = tokenData.launch;
    data.maxBalance = tokenData.maxBalance;
    data.fee = tokenData.fee;
    data.tax = tokenData.tax;
    data.ref = tokenData.ref;
    data.holders = IIncubatorToken(token).totalHolders();
    data.routerIncubator = tokenData.routerIncubator;
    data.pairIncubator = tokenData.pairIncubator;
    data.routerFinal = tokenData.routerFinal;
    data.escaped = tokenData.escaped;
    data.initialSupply = tokenData.initialSupply;
    data.totalSupply = IERC20(token).totalSupply();
    data.ethReserveEscapeTarget = tokenData.ethReserveEscapeTarget;
    data.ethReserveVirtualInitial = tokenData.ethReserveVirtualInitial;
    data.tokenReserveInitial = tokenData.tokenReserveInitial;
    data.creationFee = tokenData.creationFee;
    data.escapeFee = tokenData.escapeFee;
    data.autoEscape = tokenData.autoEscape;

    if (tokenData.escaped == 0) {
      data.ethReserve = uint112(IERC20(_WETH_INCUBATOR).balanceOf(tokenData.pairIncubator));
      data.tokenReserve = uint112(IERC20(token).balanceOf(tokenData.pairIncubator));
    } else {
      data.ethReserveEscaped = tokenData.ethReserveEscaped;
      data.tokenReserveEscaped = tokenData.tokenReserveEscaped;
    }
  }

  function deployToken(bytes32 _salt, string memory _name, string memory _symbol, uint24 _maxBalance, uint24 _tax, uint32 _launch, address _routerFinal, bool _autoEscape, address _referral) external payable returns (address token) {
    if (_PAUSED == 1) { revert ErrorPaused(); }
    if (!_routerData[_routerFinal].enabled) { revert ErrorRouterUnavailable(_routerFinal); }
    if (_referral != address(0) && (_referral == msg.sender || !_creatorData[_referral])) { revert ErrorReferral(); }

    uint256 value = msg.value;

    if (value < _CREATION_FEE) { revert ErrorTokenMinimumValue(_CREATION_FEE); }
    if (_maxBalance < 100 && _maxBalance > 100_000) { revert ErrorTokenMaxBalance(_maxBalance); } // Min. 0.1%
    if (_tax > 10_000) { revert ErrorTokenTax(_tax); } // Max. 10%

    Token _token = new Token{ salt: _salt }(address(this), msg.sender, _name, _symbol, _DECIMALS, _TOTAL_SUPPLY);

    token = address(_token);

    TokenData storage tokenData = _tokenData[token];

    tokenData.creator = msg.sender;
    tokenData.salt = _salt;
    tokenData.referral = _referral;
    tokenData.creation = _timestamp();
    tokenData.maxBalance = _maxBalance;
    tokenData.fee = _SWAP_FEE;
    tokenData.tax = _tax;
    tokenData.launch = _launch > _timestamp() ? _launch : _timestamp();
    tokenData.ref = _referral == address(0) ? uint24(0) : _REFERRAL_FEE;
    tokenData.initialSupply = _TOTAL_SUPPLY;
    tokenData.routerIncubator = _ROUTER_INCUBATOR;
    tokenData.pairIncubator = IUniswapV2Factory(IUniswapV2Router(_ROUTER_INCUBATOR).factory()).createPair(token, _WETH_INCUBATOR);
    tokenData.tokenReserveInitial = uint112(_percentage(_TOTAL_SUPPLY, uint256(_TOKEN_INITIAL_PERCENT)));
    tokenData.ethReserveVirtualInitial = _ETH_RESERVE_VIRTUAL_INITIAL;
    tokenData.ethReserveEscapeTarget = _ETH_RESERVE_ESCAPE_TARGET;
    tokenData.routerFinal = _routerFinal;
    tokenData.autoEscape = _autoEscape;

    _tokenList.push(token);
    _pairData[tokenData.pairIncubator] = token;

    if (!_creatorData[tokenData.creator]) { _creatorData[tokenData.creator] = true; }
    if (_CREATION_FEE > 0) {
      tokenData.creationFee = _CREATION_FEE;

      if (_TREASURY != address(0)) {
        (bool success,) = _TREASURY.call{ value: tokenData.creationFee }("");

        if (!success) { revert ErrorTransfer(_TREASURY, tokenData.creationFee); }
      }

      unchecked {
        value -= _CREATION_FEE;
      }
    }

    IIncubatorToken(token).initialize(tokenData.routerIncubator, tokenData.pairIncubator, tokenData.maxBalance, tokenData.tax, tokenData.launch, _unauthorizedList);
    IERC20(token).transfer(tokenData.pairIncubator, uint256(tokenData.tokenReserveInitial));

    emit TokenDeployed(token, tokenData.creator, _salt);

    IIncubatorPair(tokenData.pairIncubator).initializePair(tokenData.creator, _SWAP_FEE, _tax, tokenData.ref, tokenData.launch, tokenData.tokenReserveInitial, _ETH_RESERVE_VIRTUAL_INITIAL, _ETH_RESERVE_ESCAPE_TARGET, _WETH_INCUBATOR, tokenData.referral, tokenData.autoEscape);

    if (value > 0) {
      address[] memory path = new address[](2);
      path[0] = _WETH_INCUBATOR;
      path[1] = token;

      IUniswapV2Router(tokenData.routerIncubator).swapExactETHForTokensSupportingFeeOnTransferTokens{ value: value }(0, path, tokenData.creator, _timestamp());
    }
  }

  function pairSwap(address user, bool buy, uint112 ethReserve, uint112 tokenReserve, uint256 ethAmount, uint256 tokenAmount, uint256 feeAmount, uint256 taxAmount, uint256 refAmount) external isPairOfToken() {
    address token = _pairData[msg.sender];

    if (_TREASURY != address(0) && feeAmount > 0) {
      (bool success,) = _TREASURY.call{ value: feeAmount }("");

      if (!success) { revert ErrorTransfer(_TREASURY, feeAmount); }
    }

    emit TokenTraded(token, _timestamp(), user, buy, ethReserve, tokenReserve, ethAmount, tokenAmount, feeAmount, taxAmount, refAmount);
  }

  function tokenEscape(uint256 amount) external payable isPairOfToken() {
    address token = _pairData[msg.sender];
    uint256 value = msg.value;
    uint256 balance = IERC20(token).balanceOf(address(this));

    TokenData storage tokenData = _tokenData[token];

    tokenData.escaped = _timestamp();
    tokenData.tokenReserveEscaped = amount;
    tokenData.ethReserveEscaped = uint112(value);

    if (_ESCAPE_FEE > 0) {
      tokenData.escapeFee = _percentage(value, uint256(_ESCAPE_FEE));

      unchecked {
        value -= tokenData.escapeFee;
      }

      { // scope to avoid "stack too deep" error
        uint256 creatorFee;
        uint256 escapeFee;

        unchecked {
          creatorFee = _percentage(tokenData.escapeFee, uint256(_ESCAPE_CREATOR_FEE));
          escapeFee = tokenData.escapeFee - creatorFee;
        }

        if (_TREASURY != address(0)) {
          (bool txTreasuryFee,) = _TREASURY.call{ value: escapeFee }("");

          if (!txTreasuryFee) { revert ErrorTransfer(_TREASURY, escapeFee); }
        }

        (bool txCreatorFee,) = tokenData.creator.call{ value: creatorFee }("");

        if (!txCreatorFee) { revert ErrorTransfer(tokenData.creator, creatorFee); }
      }
    }

    IIncubatorToken(token).escape();

    if (_AUTHORIZED != address(0)) {
      IERC20(token).transfer(_AUTHORIZED, balance);

      (bool success,) = _AUTHORIZED.call{ value: value }("");

      if (!success) { revert ErrorTransfer(_AUTHORIZED, value); }
    }

    emit TokenEscaped(token, tokenData.escaped, tokenData.ethReserveEscaped, tokenData.tokenReserveEscaped, tokenData.escapeFee);
  }

  function currentStatus() external view returns (currentStatusView memory data) {
    data.paused = _PAUSED;
    data.decimals = _DECIMALS;
    data.swapFee = _SWAP_FEE;
    data.referralFee = _REFERRAL_FEE;
    data.escapeFee = _ESCAPE_FEE;
    data.escapeCreatorFee = _ESCAPE_CREATOR_FEE;
    data.tokenInitialPercent = _TOKEN_INITIAL_PERCENT;
    data.ethReserveVirtualInitial = _ETH_RESERVE_VIRTUAL_INITIAL;
    data.ethReserveEscapeTarget = _ETH_RESERVE_ESCAPE_TARGET;
    data.creationFee = _CREATION_FEE;
    data.totalSupply = _TOTAL_SUPPLY;
    data.routerIncubator = _ROUTER_INCUBATOR;
  }

  function setTreasury(address treasury) external onlyOwner {
    _TREASURY = treasury;
  }

  function withdrawETH(address to, uint256 value) external onlyOwnerOrAuthorized {
    (bool success,) = to.call{ value: value }("");

    if (!success) { revert ErrorTransfer(to, value); }

    emit WithdrawnETH(to, value);
  }

  function withdrawERC20(address token, address to, uint256 value) external onlyOwnerOrAuthorized {
    IERC20(token).transfer(to, value);

    emit WithdrawnERC20(token, to, value);
  }

  function _timestamp() private view returns (uint32) {
    unchecked {
      return uint32(block.timestamp % 2**32);
    }
  }

  function _percentage(uint256 value, uint256 bps) private pure returns (uint256) {
    unchecked {
      return (value * bps) / 100_000;
    }
  }

  receive() external payable {}
}

/*

 █▀ █▀█ █▄░█ █ █▀▀ █▀▀ ▄▀█ █▀▀ ▀█▀ █▀█ █▀█ █▄█
 ▄█ █▄█ █░▀█ █ █▄▄ █▀░ █▀█ █▄▄ ░█░ █▄█ █▀▄ ░█░

  Trade on SonicFactory and have fun!
  Web:      https://sonicfactory.fun/

*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

import "./ERC20.sol";

contract Token is ERC20 {
  address private immutable _creator;
  address private _owner;
  address private _router;
  address private _pair;

  bool private _escaped;
  bool private _initialized;
  uint24 private _maxBalance;
  uint24 private _tax;
  uint32 private _launch;

  mapping(address => bool) private _unauthorized;

  struct HolderView {
    address holder;
    uint256 balance;
  }

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  error ErrorUnauthorized(address sender);
  error ErrorAlreadyInitialized();
  error ErrorUnapprovable();
  error ErrorMaxBalanceExceeded();
  error ErrorInvalidRecipient(address to);
  error ErrorInvalidRange();

  modifier onlyOwner() {
    if (msg.sender != _owner) { revert ErrorUnauthorized(msg.sender); }

    _;
  }

  constructor(address _owner_, address _creator_, string memory _name_, string memory _symbol_, uint8 _decimals_, uint256 _totalSupply_) ERC20(_name_, _symbol_, _decimals_) payable {
    _creator = _creator_;
    _owner = _owner_;
    _mint(_owner_, _totalSupply_);
  }

  function initialize(address _router_, address _pair_, uint24 _maxBalance_, uint24 _tax_, uint32 _launch_, address[] calldata _unauthorized_) external onlyOwner {
    if (_initialized) { revert ErrorAlreadyInitialized(); }

    unchecked {
      uint256 cnt = _unauthorized_.length;

      for (uint256 i; i < cnt; i++) { _unauthorized[_unauthorized_[i]] = true; }
    }

    _router = _router_;
    _pair = _pair_;
    _maxBalance = _maxBalance_;
    _tax = _tax_;
    _launch = _launch_;
    _initialized = true;
  }

  function owner() external view returns (address) {
    return _owner;
  }

  /// @notice Returns the creator address
  function creator() external view returns (address) {
    return _creator;
  }

  function approve(address spender, uint256 value) public override returns (bool) {
    if (!_escaped && spender != _router) { revert ErrorUnapprovable(); }

    return super.approve(spender, value);
  }

  function permit(address owner_, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public override {
    if (!_escaped && spender != _router) { revert ErrorUnapprovable(); }

    super.permit(owner_, spender, value, deadline, v, r, s);
  }

  function _transferCheck(address from, address to, uint256 value) private view {
    if (_escaped || ((from == _owner && to == _pair) || ((!_escaped && to == _owner) || value == 0 || to == address(0xdEaD) || to == _router || to == _pair))) { return; }

    if (!_escaped) {
      if (_unauthorized[to]) { revert ErrorInvalidRecipient(to); }

      unchecked {
        if (_maxBalance == 100_000 || _balance[to] + value <= _percentage(_totalSupply, uint256(_maxBalance))) { return; }
      }
    }

    revert ErrorMaxBalanceExceeded();
  }

  function transfer(address to, uint256 value) external virtual override returns (bool) {
    _transfer(msg.sender, to, value);

    return true;
  }

  function _transfer(address from, address to, uint256 value) internal virtual override {
    _transferCheck(from, to, value);

    super._transfer(from, to, value);
  }

  function transferFrom(address from, address to, uint256 value) public override returns (bool) {
    if (!_escaped && msg.sender == _router && to == _pair && _allowance[from][_router] != type(uint256).max) { super._approve(from, _router, type(uint256).max, false); }

    _transferCheck(from, to, value);

    return super.transferFrom(from, to, value);
  }

  function totalHolders() external view returns (uint24 total) {
    return _totalHolders;
  }

  function holders(uint256 offset, uint256 limit) public view returns (HolderView[] memory) {
    if (offset >= _totalHolders) { revert ErrorInvalidRange(); }

    unchecked {
      if (offset + limit > _totalHolders) { limit = _totalHolders - offset; }
    }

    HolderView[] memory list = new HolderView[](limit);

    unchecked {
      uint256 j;

      for (uint256 i = offset; j < limit; i++) {
        address holder = _holders[i];

        if (holder == address(0xdEaD) || _balance[holder] == 0) { continue; }

        list[j].holder = holder;
        list[j].balance = _balance[holder];

        ++j;
      }
    }

    return list;
  }

  function maxBalance() external view returns (uint24) {
    return _maxBalance;
  }

  function tax() external view returns (uint24) {
    return _tax;
  }

  function launch() external view returns (uint32) {
    return _launch;
  }

  /// @notice Returns True if token has reached the target MC and is now tradeable on a public DEX
  function escaped() external view returns (bool) {
    return _escaped;
  }

  function escape() external onlyOwner {
    if (_escaped) { revert ErrorUnauthorized(msg.sender); }
    if (_maxBalance < 100_000) { _maxBalance = 100_000; } // 100%

    address _previousOwner = _owner;

    delete _tax;
    delete _owner;
    delete _router;
    delete _pair;

    _escaped = true;

    emit OwnershipTransferred(_previousOwner, _owner);
  }

  function _percentage(uint256 value, uint256 bps) private pure returns (uint256) {
    unchecked {
      return (value * bps) / 100_000;
    }
  }

  function _timestamp() private view returns (uint32) {
    unchecked {
      return uint32(block.timestamp % 2**32);
    }
  }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

abstract contract Ownable {
  address internal _owner;

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  error ErrorUnauthorized(address sender);

  modifier onlyOwner() {
    if (msg.sender != _owner) { revert ErrorUnauthorized(msg.sender); }

    _;
  }

  function renounceOwnership() external onlyOwner {
    _transferOwnership(address(0));
  }

  function transferOwnership(address newOwner) external onlyOwner {
    require(newOwner != address(0));

    _transferOwnership(newOwner);
  }

  function _transferOwnership(address newOwner) internal {
    address oldOwner = _owner;
    _owner = newOwner;

    emit OwnershipTransferred(oldOwner, newOwner);
  }

  function owner() external view returns (address) {
    return _owner;
  }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IUniswapV2Factory {
  function createPair(address tokenA, address tokenB) external returns (address pair);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IUniswapV2Router {
  function WETH() external pure returns (address);
  function factory() external pure returns (address);
  function addLiquidityETH(address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
  function swapExactETHForTokensSupportingFeeOnTransferTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IIncubatorPair {
  function initializePair(address creator, uint24 fee, uint24 tax, uint24 ref, uint32 launch, uint112 tokenInitialReserve, uint112 ethInitialVirtualReserve, uint112 ethReserveEscapeTarget, address WETH, address referral, bool autoEscape) external;
  function getTraderData(address user) external view returns (uint32 lastActivity, uint32 buys, uint32 sells, uint256 buy_volume, uint256 sell_volume);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IIncubatorToken {
  function totalHolders() external view returns (uint24);
  function initialize(address router, address pair, uint24 maxBalance, uint24 tax, uint32 launch, address[] calldata unauthorized) external;
  function escape() external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IERC20 {
  function name() external view returns (string memory);
  function symbol() external view returns (string memory);
  function decimals() external view returns (uint8);
  function balanceOf(address account) external view returns (uint256);
  function totalSupply() external view returns (uint256);
  function transfer(address to, uint256 value) external returns (bool);
  function approve(address spender, uint256 value) external returns (bool);
  function burn(uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

abstract contract ERC20 {
  uint8 private immutable _decimals;
  uint24 internal _totalHolders;
  uint256 internal _totalSupply;

  string private _name;
  string private _symbol;
  bytes32 public immutable DOMAIN_SEPARATOR;
  bytes32 private constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

  address[] internal _holders;

  mapping(address => uint256) private _nonces;
  mapping(address => uint256) internal _balance;
  mapping(address => mapping(address => uint256)) internal _allowance;
  mapping(address => bool) internal _holderData;

  event Approval(address indexed owner, address indexed spender, uint256 value);
  event Transfer(address indexed from, address indexed to, uint256 value);

  error ERC20InvalidApprover(address owner);
  error ERC20InvalidSpender(address spender);
  error ERC20InvalidSender(address sender);
  error ERC20InvalidReceiver(address to);
  error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 value);
  error ERC20InsufficientBalance(address owner, uint256 balance, uint256 value);
  error ERC2612ExpiredSignature(uint256 deadline);
  error ERC2612InvalidSigner(address signer, address owner);

  constructor(string memory _name_, string memory _symbol_, uint8 _decimals_) {
    _name = _name_;
    _symbol = _symbol_;
    _decimals = _decimals_;

    DOMAIN_SEPARATOR = keccak256(abi.encode(keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(_name)), keccak256(bytes("1")), block.chainid, address(this)));
  }

  function name() external view returns (string memory) {
    return _name;
  }

  function symbol() external view returns (string memory) {
    return _symbol;
  }

  function decimals() external view returns (uint8) {
    return _decimals;
  }

  function totalSupply() external view returns (uint256) {
    return _totalSupply;
  }

  function balanceOf(address account) external view returns (uint256) {
    return _balance[account];
  }

  function allowance(address owner, address spender) public view returns (uint256) {
    return _allowance[owner][spender];
  }

  function approve(address spender, uint256 value) public virtual returns (bool) {
    _approve(msg.sender, spender, value, true);

    return true;
  }

  function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual {
    if (block.timestamp > deadline) { revert ERC2612ExpiredSignature(deadline); }

    unchecked {
      address signer = ecrecover(keccak256(abi.encodePacked(hex"1901", DOMAIN_SEPARATOR, keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _nonces[owner]++, deadline)))), v, r, s);

      if (signer != owner) { revert ERC2612InvalidSigner(signer, owner); }
    }

    _approve(owner, spender, value, true);
  }

  function nonces(address owner) external view returns (uint256) {
    return _nonces[owner];
  }

  function transfer(address to, uint256 value) external virtual returns (bool) {
    _transfer(msg.sender, to, value);

    return true;
  }

  function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
    if (value > 0) {
      address spender = msg.sender;
      uint256 allowed = allowance(from, spender);

      if (allowed < value) { revert ERC20InsufficientAllowance(to, allowed, value); }

      if (allowed != type(uint256).max) {
        unchecked {
          _approve(from, spender, allowed - value, false);
        }
      }
    }

    _transfer(from, to, value);

    return true;
  }

  function burn(uint256 value) external returns (bool) {
    _transfer(msg.sender, address(0xdEaD), value);

    return true;
  }

  function _approve(address owner, address spender, uint256 value, bool emitEvent) internal {
    if (owner == address(0)) { revert ERC20InvalidApprover(owner); }
    if (spender == address(0)) { revert ERC20InvalidSpender(spender); }

    _allowance[owner][spender] = value;

    if (emitEvent) { emit Approval(owner, spender, value); }
  }

  function _transfer(address from, address to, uint256 value) internal virtual {
    if (from == address(0)) { revert ERC20InvalidSender(from); }
    if (to == address(0) || to == address(this)) { revert ERC20InvalidReceiver(to); }
    if (_balance[from] < value) { revert ERC20InsufficientBalance(from, _balance[from], value); }

    if (value > 0) {
      unchecked {
        _balance[from] -= value;

        if (_balance[from] == 0) { --_totalHolders; }

        if (to == address(0xdEaD)) {
          _totalSupply -= value;
        } else {
          if (_balance[to] == 0) { ++_totalHolders; }

          _balance[to] += value;

          if (!_holderData[to]) {
            _holderData[to] = true;
            _holders.push(to);
          }
        }
      }
    }

    emit Transfer(from, to, value);
  }

  function _mint(address to, uint256 value) internal {
    if (to == address(0) || to == address(0xdEaD)) { revert ERC20InvalidReceiver(to); }

    unchecked {
      if (_balance[to] == 0) { ++_totalHolders; }

      _totalSupply += value;
      _balance[to] += value;

      if (!_holderData[to]) {
        _holderData[to] = true;
        _holders.push(to);
      }
    }

    emit Transfer(address(0), to, value);
  }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):